harry young
harry young

Reputation: 770

how to emit from a controller function with socket.io?

I'm building my first MERN app [a message board] and trying to add a mail notification using socket.io.

So far I have in server.js:

const io = socketio(expressServer);
const connectedUsers = {};

io.on('connection', (socket) => {
  socket.emit('messageFromServer', { data: 'Welcome to the server' });
  socket.on('messageToServer', (dataFromClient) => {
    connectedUsers[dataFromClient.username] = socket;
  });
});

to emit from my controller file, do I need the io object or just the socket, and how can I share it/them with the controller file?

All help greatly appreciated!

Upvotes: 1

Views: 1153

Answers (1)

Matt
Matt

Reputation: 74680

Setup an external file for your user tracking connectedUsers.js to avoid circular dependencies.

const connectedUsers = {}

module.exports = { connectedUsers }

Server Setup:

const { connectedUsers } = require('./connectedUsers')

io.on('connection', (socket) => {
  socket.on('messageToServer', (dataFromClient) => {
    connectedUsers[dataFromClient.username] = socket;
  });
});

The next problem is getting the io instance to the router/controller. I normally attach the io instance to the app in the server setup for this.

app.io = io

Then in the router/controller you can access the io instance from the req object:

const { connectedUsers } = require('./connectedUsers')

router.post('/message', function(req,res){
  if ( connectedUsers[req.body.username] && connectedUsers[req.body.username].id) {
     const id = connectedUsers[req.body.username].id
     req.app.io.to(id).emit({ msg: 'blah' })
  }
})

The if check above is an example of the code that will pop up everywhere you use connectedUsers. The simple object often turns into a singleton class ConnectedUsers {} instance so common code can be attached rather that littered throughout controllers.

Upvotes: 1

Related Questions