Use socket.io inside express routes file

I am trying to use Socket.io with Node.js and emit a socket in the route logic.

I have a pretty standard version of Express 3 with the server.js file that is on the route, and then I have index.js, which is in the route folders that export all the pages / public functions of the site. Therefore, they look like this:

exports.index = function (req, res) { res.render('index', { title: "Awesome page" }); }; 

with the routing defined in server.js, for example:

 app.get('/',routes.index); 

I assume that I need to create a socket.io object in server.js since it needs a server object, but how can I access this object and emit it from the index.js export functions?

+15
source share
6 answers

You can configure the routes file as a function and pass the Socket.IO object if necessary.

 module.exports = function(io) { var routes = {}; routes.index = function (req, res) { io.sockets.emit('payload'); res.render('index', { title: "Awesome page" }); }; return routes; }; 

Then the following routes are required:

 var express = require('express'); var app = express(); var http = require('http'); var server = http.createServer(app); var io = require('socket.io').listen(server); var routes = require('./routes')(io); 
+17
source

Now there is a better way to do this with Express 4.0.

You can use app.set () to store a reference to an io object.

Basic configuration:

 var app = require('express')(); var server = app.listen(process.env.PORT || 3000); var io = require('socket.io')(server); // next line is the money app.set('socketio', io); 

Internal route or middleware:

 exports.foo = function(req,res){ // now use socket.io in your routes file var io = req.app.get('socketio'); io.emit('hi!'); } 

Information about app.set() and app.get() given below:

app.set (name, value)

Assigns a setting name to a value. You can store any value you want, but certain names can be used to customize server behavior. These special names are listed in the application settings table .

Calling app.set('foo', true) for a boolean property is the same as calling app.enable('foo') . Similarly, calling app.set('foo', false) for a boolean property is similar to calling app.disable('foo') .

Get the setting value using app.get() .

Source: https://expressjs.com/en/api.html#app.set

+81
source

Aarosil's answer was great, but I ran into the same problem as Victor with managing client connections using this approach. For each reboot on the client, you will receive on the server the same number of repeated messages (2 repeated = 2 duplicates, 3 = 3 duplicates, etc.).

Turning around aarosil's answer, I used this approach to use the socket object in the routes file and manage messages / manage duplicate messages:

Server internal file

 // same as aarosil (LIFESAVER) const app = require('express')(); const server = app.listen(process.env.PORT || 3000); const io = require('socket.io')(server); // next line is the money app.set('socketio', io); 

Inside Routes File

 exports.foo = (req,res) => { let socket_id = []; const io = req.app.get('socketio'); io.on('connection', socket => { socket_id.push(socket.id); if (socket_id[0] === socket.id) { // remove the connection listener for any subsequent // connections with the same ID io.removeAllListeners('connection'); } socket.on('hello message', msg => { console.log('just got: ', msg); socket.emit('chat message', 'hi from server'); }) }); } 
+12
source

Misuse

 global.io = require('socket.io').listen(server); 
+3
source

The addition is too late here, but I wanted to access the socket in my routes and specifically wanted to send a message after saving to the database. I used the answer provided by @aarosil to set / receive the io object, sent each client its socket ID when connected, then used the socket ID in the route to be able to use socket.broadcast.emit() instead of io.emit() .

On server:

 const io = require('socket.io')(server) app.set('socketio', io) io.on('connect', socket => { socket.emit('id', socket.id) // send each client their socket id }) 

I send a socket id with every request, and then I can do the following in my routes:

 router.post('/messages', requireToken, (req, res, next) => { // grab the id from the request const socketId = req.body.message.socketId // get the io object ref const io = req.app.get('socketio') // create a ref to the client socket const senderSocket = io.sockets.connected[socketId] Message.create(req.body.message) .then(message => { // in case the client was disconnected after the request was sent // and there no longer a socket with that id if (senderSocket) { // use broadcast.emit to message everyone except the original // sender of the request !!! senderSocket.broadcast.emit('message broadcast', { message }) } res.status(201).json({ message: message.toObject() }) }) .catch(next) }) 
+1
source

module.parent.exports.server will also work if you export the server to the parent module.

0
source

Source: https://habr.com/ru/post/954010/


All Articles