Reputation: 2934
I know that usually you would have app.js
create the socket server, and pass that instance down to your router, which in turn can pass it to controller methods. As shown here (Socket.io emit from Express controllers)
However, I have a controller method that needs to emit progress to any client who happens to be listening, but this method can be executed from many different routes, and other controllers, and I don't really want to have to pass a reference to socket
around all these other parts of the app.
Is there a better way to do it?
I was thinking something like a socketio
helper module. The app.js
module passes it a reference to io
, which can be retrieved later....
app.js
var io = require('socket.io').listen(server);
require('./helpers/socketio').set(io);
helpers/socketio.js
var io=null;
exports.set = function(socketio) {
io=socketio;
}
exports.get = function() {
return io;
}
Then whenever you need it in the app..
var io = require('./helpers/socketio').get();
io.emit('message', {a:1, b:2});
Is there a cleaner way to do this? Clearly it could return null, which you would have to check for. It just doesn't feel right....
Upvotes: 4
Views: 2608
Reputation: 131
This works for me:
Create a js file and add something like this
const service = {}
const server = require('http').Server()
const io = require('socket.io')(server, {
cors: {
origins: ['http://localhost:4200']
}
});
service.inicializar = () => {
io.on('connection', (socket) => {
const idHandShake = socket.id;
const { email } = socket.handshake.query;
socket.join(email);
console.log(`Conexion establecida --> ${idHandShake}`);
//Este metodo escucha lo que envia el front y tiene la capacidad de emitir hacia otros miembros de la sala.
socket.on('event', (res) => {
const data = res
console.log(data)
//Envia un mensaje a todos los participantes del room
socket.to(email).emit('event', data);
})
})
return io;
}
service.emitEvent = async (email, mensaje) => {
const sockets = await io.in(email).fetchSockets();
sockets[0].emit('event', mensaje);
}
service.emitSesionIniciada = async (email, mensaje) => {
console.log('email de session iniciada: ', email);
const sockets = await io.in(email).fetchSockets();
sockets[0].emit('sessionIniciada', mensaje);
}
module.exports = service;
you can see that Im exporting some methods on service object. You can use it later from other files just refering this one
In your server.js or app.js o whatever you run the server
const socket = require('./src/services/socket')---< this is refering the file you created
const io = socket.inicializar() ---> this call it just one. Initialize the server.
Hope this helps. Regards.
Upvotes: 0
Reputation: 83
A solution that worked for me was assigning io to app as:
app.io = io in app.js
then anywhere you have access to the app object you have a link to the socket.
example :
file: index.js my main routing file for authenticated users
const express = require('express');
const router = express.Router();
const { ensureAuthenticated } = require('../config/auth');
... rest of the file
// Dashboard
router.get('/dashboard', ensureAuthenticated, (req, res) =>{
res.render('dashboard') //sends the dashboard page to the user
req.app.io.emit('hello',req.user.name + ' Has Joined' )
// lets every one else know that a new user has joined
})
Upvotes: 2
Reputation: 505
Modules are cached after the first time they are loaded.
Actually, you can verify socket.io at helper/socketio.js
.
Although you call require()
that socketio.js
from other files, node.js will execute code on that file only one time.
You can look Node Documentation
Upvotes: 1