I am working on a node project where I need to use websockets. I got the basic implementation working for socket.io in my project. Here is the code for server.js so far
import app from '../app';
import http from 'http';
import socket from 'socket.io';
var server = http.createServer(app);
server.listen(app.get("port"));
server.on('error', onError);
server.on('listening', onListening);
const io = socket(server);
io.on('connection', (socket) => {
console.log(`connected ${socket.id}`);
socket.on('disconnect', () => {
console.log('disconnected');
});
});
Now if I need to call socket from another javascript file, how do I do that?
Something like this: From a.js I would like to call emit message from download function. The problem is that I don't have reference to socket object in a.js. It was defined in my server.js file. Any suggestions?
export const download = () => {
//after file is downloaded, emit message using socket.io to user
}
you need to inject the object into a function that you're calling. is a Dependency Injection principle in programming.
you can
a.js
export const download = (io) => { // io is the reference
//do something with io like io.emit
}
then in your server you need to import the download function then pass the io in your code.
import {download} from "<src/file/of/a.ts>"
// somewhere in the code in server.js
download(io);
for Dependency Injection Principle reference https://en.wikipedia.org/wiki/Dependency_injection
and What is dependency injection?
Related
I'm trying to make a very simple server script for a game using sockets.
I basically have a server.js that uses express and socket.io to accept a connection and serve whatever is in public folder.
let express = require("express");
let app = express();
app.use(express.static("public"));
let server = app.listen(3000);
let socket = require("socket.io");
let io = socket(server);
io.sockets.on("connection", newConnection);
function newConnection(socket) {
console.log("New connection: " + socket.id);
}
This is a basic script that accepts connections from a client and just prints when a client has connected.
I already did a npm init, installed express and socket.io and I run it using npm start and it works correctly.
Now, I have build a class Game in a file Game.js and when a client connects I just want to instantiate the game.
Something like:
function newConnection(socket) {
console.log("New connection: " + socket.id);
let game = new Game();
}
The problem is that I don't know how to import Game.
I tried using import, but apparently I'm not using the right syntax:
import "game.js"
import "game.js"
^^^^^^^^^
SyntaxError: Unexpected string
I just want inside my server.js to use a class that I implemented in a file that is in the same folder. How can I do this?
When using node, you don't use the "import" keyword but rather "require" (Like you already did with express and socket.io in your server.js).
This would look something like:
let game = require("game.js");
Don't forget to export the needed functions inside your game.js.
exports.newConnection = function(socket) {
console.log("New connection: " + socket.id);
let game = new Game();
}
This way, you can call your newConnection function from inside the server.js by typing:
io.sockets.on("connection", game.newConnection);
If you only need one function from inside a class, you can also just "require" a single function by explicitly stating this function, like:
let gameconnection = require("game.js").newConnection;
and then calling it with:
io.sockets.on("connection", gameconnection);
I try to setup a very basic socket.io bridge between my server (listening on port 8080) and my client (served by react-scripts on port 3000). Nothing happens and I don't even have any error to start debugging.
This is my server :
const server = require('http').createServer()
const Io = require('socket.io')
const io = new Io(server, {
path: '/live'
})
io.on('connection', () => console.log('DID CONNECT'))
server.listen(8080)
And this is my client :
import React from 'react'
import makeSocket from 'socket.io-client'
const socket = makeSocket('http://localhost:8080/live')
socket.on('connect', () => console.log('DID CONNECT'))
export default () => <h1>Demo</h1>
No error, no success log, nothing. What is going on ? Thanks.
Edit : If that may help, it actually seems like I get this error sometimes on browser-side (using Chromium) :
GET http://localhost:8080/socket.io/?EIO=3&transport=polling&t=MuLOZwa net::ERR_EMPTY_RESPONSE
I'm running an express based apollo graphQL server using apollo-server-express.
import express from 'express'
import cors from 'cors'
import server from './graphql/schema'
app.use(cors())
server.applyMiddleware({ app, path: '/graphql' })
app.listen(port, async () => {
if (process.env.NODE_ENV !== 'production') {
console.log('Listening on port ' + port)
}
})
export default app
Now I need to connect to some other applications from my client. Therefore he provides me with HL7 data. He told me to 'use a socket to get the HL7 data', which my application can use.
I just don't have a clue how to implement a socket connection at all.
Doing some researches brought me to libraries like socket.io, which should be used like this (for express):
const app = require('express')();
const server = require('http').createServer(app);
const io = require('socket.io')(server);
io.on('connection', () => { /* … */ });
server.listen(3000)
I don't understand how to implement the io in my existing code shown above.
I never used or implemented a socket connection at all, so I have very big understanding problems with that. Maybe the socket.io library is not the correct thing for my needs.
I do not have any knowlege about HL7 data, I think your another app has been writen by Java.
But, if you want to implement a socket.io server with apollo-server-express, just follow socket.io official document and attach a http server to express app and socket.io, then start your http server.
import express from 'express'
import cors from 'cors'
import GraphQLServer from './graphql/schema'
import socketIO from 'socket.io'
import http from 'http'
let app = express() // You missed this line ?
let httpServer = http.Server()
let io = socketIO(httpServer)
app.use(cors())
GraphQLServer.applyMiddleware({ app, path: '/graphql' })
httpServer.listen(port, async () => { // I don't see your `port`
if (process.env.NODE_ENV !== 'production') {
console.log('Listening on port ' + port)
}
})
io.on('connection', (socket) => {
console.log('A client connected', socket.id)
});
export default app
I am creating an app with nodejs. In the app, I have a app.js script that is the entrypoint that initializes both the app, as an expressjs app, and the http server that I use.
Just to clarify: modules here are not npm modules, they are my own files. I've written the app in modules. They are just seperate script files used by require()-ing them.
This app has several modules that a main module handler initializes. It reads the contents of a folder, which contains my own modules, and then by convention call the .initialize on each module after running a require() call on the filenames without the .js extension.
However, I have 1 module that needs the app variable to create an endpoint, and 1 module that needs the httpServer variable to create a web socket. Both of these are instansiated in app.js.
Seeing as I don't know what kind of modules will be in the folder, I don't really want to send app and httpServer to every module if they are just needed by 1 module each. Something like dependency injection would fit nice, but is that possible without to much overhead?
Right now I just temporarily added app and httpServer to the GLOBAL object.
What I usually do is have app.js export app so that modules elsewhere in my app can require it directly rather than having to deal with passing it around everywhere. I also slightly modify app.js so that it won't "listen" if it is required as a module that way later on if i decide to wrap it with another app, I can with minimal changes. This is not important to your question, I just find it give me more control when unit testing. All you really need from the code below is module.exports = app
'use strict';
var express = require('express'),
app = express(),
config = require('config'),
pkg = require('./package.json');
// trust reverse proxies
app.enable('trust proxy');
app.set('version', pkg.version);
module.exports = app; // <--- *** important ***
if (app.get('env') !== 'production') {
app.set('debug', true);
}
// calling app.boot bootstraps the app
app.boot = function (skipStart) { // skipStart var makes it easy to unit test without actually starting the server
// add middleware
require('./middleware/');
// setup models
app.set('models', require('./models'));
// setup routes
require('./routes/');
// wait for a dbconnection to start listening
app.on('dbopen', function () {
// setup hosting params
if (!skipStart) {
let server = app.listen(config.port, function () {
app.emit('started');
console.log('Web Server listening at: http://%s:%s', server.address().address, server.address().port);
// mail server interceptor for dev
if (app.get('env') !== 'production') {
// Config smtp server for dev
let SMTPServer = require('smtp-server').SMTPServer,
mailServer = new SMTPServer({
secure: false,
disabledCommands: ['STARTTLS'],
onData: function(stream, session, callback){
stream.pipe(process.stdout); // print message to console
stream.on('end', callback);
},
onAuth: function (auth, session, callback) {
callback(null, {user: 1, data: {}});
}
});
// Start smtp server
mailServer.listen(1025, '0.0.0.0');
} else {
// start agenda jobs only on production
require('./jobs.js');
console.log('Agenda Jobs Running.');
}
});
} else {
app.emit('booted');
}
});
};
// If this is the main module, run boot.
if (require.main === module) {
// move all of this to next tick so we can require app.js in other modules safely.
process.nextTick(app.boot);
}
Suppose you want to initialize 2 file from main app.js
app.js
var socketIni = require('./socketini.js');//You have to pass server
var xyz = require('./xyz.js')//you have to pass app
var app = express();
var server=http.createServer(app);
socketIni(server);
xyz(app);
socketini.js
module.exports = function(server){
//your socket initilize goes here
var io = require('socket.io').listen(server);
}
xyz.js
module.exports = function(app){
//you can access app here
}
I'm quite new to Node.js / Express, and I'm using it as a backend for an AngularJS app. I've looked all over StackOverflow for some help on my problem, but I can't seem to figure out how to port the suggestions to my code.
My application works as follows:
A long running Scala process periodically sends my Node.js application log messages. It does this by posting to an HTTP API
When the post is received, my application writes the log message to MongoDB
The log messages are then sent in real time to the Angular client.
I am having a problem with Node's modules, as I can't figure out how to refer to the socket instance in the Express controller.
As you can see, in server.js, socket.io is instantiated there. However, I would like the controller itself, logs.js, to be able to emit using the socket.io instance.
How can I refer to io in the controller? I'm not sure how to pass the io instance to the controller so I can emit messages?
Here is some of the Node code:
server.js
var app = express(),
server = require('http').createServer(app),
io = require('socket.io').listen(server);
require('./lib/config/express')(app);
require('./lib/routes')(app);
server.listen(config.port, config.ip, function() {
console.log('Express server listening on %s:%d, in %s mode', config.ip, config.port, app.get('env'));
});
io.set('log level', 1); // reduce logging
io.sockets.on('connection', function(socket) {
console.log('socket connected');
socket.emit('message', {
message: 'You are connected to the backend through the socket!'
});
});
exports = module.exports = app;
routes.js
var logs = require('./controllers/logs'),
middleware = require('./middleware');
module.exports = function(app) {
app.route('/logs')
.post(logs.create);
}
logs.js
exports.create = function(req, res) {
// write body of api request to mongodb (this is fine)
// emit log message to angular with socket.io (how do i refer to the io instance in server.js)
};
You can use a pattern based on standard JS closures. The main export in logs.js will not be the controller function itself, but a factory function that will accept all needed dependencies, and create the controller:
exports.create = function(socket) {
return function(req, res) {
// write body of api request to mongodb
socket.emit();
}
}
Then, when you want to use it:
app.route('/logs').post(logs.create(socket));
Since you set up your routes in a separate package, you have to use the same pattern in routes.js - routes should receive the socket to use as a parameter.
This pattern works well if you want to handle those things with DI later, or test your controllers with mock "sockets".