Adam Zerner
Adam Zerner

Reputation: 19278

io.sockets.in(roomName).on(myEvent) not working after join

I want to create rooms dynamically (based on what request comes in from the front end). I followed this gist.

I want a particular room to listen for events and broadcast out to the other members in the room. I'm not sure why the following code isn't doing that. In particular, why the second log statement never happens.

io.sockets.on('connection', function (socket) {
  socket.on('joinRoom', function (roomName) {
    socket.join(roomName, function () {
      console.log('joined ' + roomName); // logs properly
      io.sockets.in(roomName).on('setVideoOnServer', function (inputUrl) {
        console.log('setVideoOnServer: ', inputUrl); // not hitting here
        io.sockets.in(roomName).emit('setVideoOnClient', inputUrl); // broadcast instead
      });
    });
  });
});

Upvotes: 0

Views: 832

Answers (1)

jfriend00
jfriend00

Reputation: 708126

Per my comment, I don't think io.sockets.in(roomName).on(...) does what you think it does.

io.sockets.in() returns a Namespace object that derives from eventEmitter. There's no override for .on() in the namespace object so all you're doing is adding a listener to the namespace object itself, not to any given socket or group of sockets (as best as I can tell by looking at the socket.io code).

There is an override for .emit() in the Namespace object which is why io.sockets.in(xxx).emit(...) works.

FYI, code for the namespace object is here: https://github.com/socketio/socket.io/blob/master/lib/namespace.js

And, even if it did what you thought, you'd be adding duplicate event handlers every time a new socket joined that room which would also probably be a problem since you'd be re-adding an event listener for every socket already in a room every time somebody new joined the room.

I think you can accomplish what you want with this:

io.sockets.on('connection', function (socket) {
  socket.on('joinRoom', function (roomName) {
    socket.join(roomName, function () {
      console.log('joined ' + roomName); // logs properly
      socket.on('setVideoOnServer', function (inputUrl) {
        console.log('setVideoOnServer: ', inputUrl); // not hitting here
        io.sockets.in(roomName).emit('setVideoOnClient', inputUrl); // broadcast instead
      });
    });
  });
});

Each time a socket is joined to the room, it will get registered for the setVideoOnServer event. So, all sockets in a room will be registered for that event.

Note: If you are ever joining a socket to multiple rooms, you will need to make sure this is doing what you want because you will be setting multiple listeners for the setVideoOnServer event, each of which will broadcast setVideoOnClient to all the other sockets.

And, if you ever leave this room, you will have to remove the event listener too.

Upvotes: 1

Related Questions