How to get current room of socket on disconnect?
Asked Answered
C

4

12

On socket.io 1.3.7, how to get the room of the socket on disconnect event?

socket.on('disconnect', function() {
    var currentRoom = ???
    socket.broadcast.in(currentRoom).emit('user:left', socket.id);
});
Caernarvonshire answered 4/12, 2015 at 16:40 Comment(0)
C
8

I solved my problem by setting currentRoomId variable on connection, so I have access to it in disconnect.

io.sockets.on('connection', function(socket) {
    var currentRoomId;
    socket.on('join', function(roomId) {
      socket.join(roomId);
      currentRoomId = roomId;
    });

   socket.on('disconnect', function() {
     socket.broadcast.in(currentRoomId).emit('user:left', socket.id);
   });
}
Caernarvonshire answered 10/12, 2015 at 22:8 Comment(1)
There is an improved answer to this without storing room ids into a variable. See my answer below.Bukavu
B
20

The rooms are already left upon the 'disconnect' event, use the 'disconnecting' event which will be emitted before the 'disconnect' event takes place whe the rooms are still accesible.

It works like this:

socket.on('disconnecting', function(){
    var self = this;
    var rooms = Object.keys(self.rooms);

    rooms.forEach(function(room){
        self.to(room).emit('user left', self.id + 'left');
    });
});
Bukavu answered 14/9, 2017 at 11:18 Comment(0)
C
8

I solved my problem by setting currentRoomId variable on connection, so I have access to it in disconnect.

io.sockets.on('connection', function(socket) {
    var currentRoomId;
    socket.on('join', function(roomId) {
      socket.join(roomId);
      currentRoomId = roomId;
    });

   socket.on('disconnect', function() {
     socket.broadcast.in(currentRoomId).emit('user:left', socket.id);
   });
}
Caernarvonshire answered 10/12, 2015 at 22:8 Comment(1)
There is an improved answer to this without storing room ids into a variable. See my answer below.Bukavu
S
1

its 2023 and this problem still remains haha, the disconnecting evet didn't helped me so I made a workarround and its working

Basically my app has this requirements:

  • A chat that has rooms
  • Only users from the same room as you should receive your message
  • When an user disconnect, all users from the same room should receive a message telling that someone has left (the problem of rooms on disconnecting)

  • So if there's a room called 'RoomA' and another called 'RoomB',
  • on the 'RoomA' we have the users [1,2,3]
  • on the 'RoomB' we have the users [4,5,6]
  • and the user 3 disconnect,
  • only users 1 and 2 should receive a message "user left"

Here is the approach that I've created and its working:

const socketIo = require('socket.io');
const clientsWithRooms = [];

const initSocket = (server) => {
  const io = socketIo(server);

  io.on('connection', (socket) => {
    console.log('Client connected');

    socket.on('join-room', (roomCode) => {
      if (roomCode) {
        console.log(`User joined ${roomCode}`)
        socket.join(roomCode);

        const isClientAlreadyInARoom = clientsWithRooms.find((client) => client.id === socket.id);

        if (isClientAlreadyInARoom) {
          isClientAlreadyInARoom.rooms.push(roomCode);
        } else {
          clientsWithRooms.push({
            id: socket.id,
            rooms: [roomCode]
          });
        }
      } else {
        console.log(`Room not found`)
        socket.emit('room-not-found', roomCode);
      }
    });

    socket.on('chat message', (message, roomCode) => {
      console.log(`Message received on room ${roomCode}: ${message}`);
      socket.to(roomCode).emit('chat message', message);
    });

    socket.on('disconnect', () => {
      const clientIndexToRemove = clientsWithRooms.findIndex((client) => client.id === socket.id);

      if (clientIndexToRemove >= 0) {
        for (const clientRoom of clientsWithRooms[clientIndexToRemove].rooms) {
          socket.to(clientRoom).emit('chat message', 'User left');
          console.log(`A client disconnected from room ${clientRoom}`);
        }

        clientsWithRooms.splice(clientIndexToRemove, 1);
      }
    });
  });
};

module.exports = { initSocket };

Please take notes that I really don't know if this is the proper way to do it but its the only one that solved my problem and I hope that it helps you too!

Sheers answered 17/10, 2023 at 14:32 Comment(1)
Maybe there'll be a problem with the messages sent if the user is on more than one room but I think that it should be really easy to implement something to prevent that, in my application the same user is not able to join 2 rooms at the same time so I dind't wrote any code to prevent that!Sheers
D
0

You could keep track of all the sockets in a globally declared array in the beginning and then check the index of that array on the disconnect event. Something like this:

var allClients = [];

io.sockets.on('connection', function(socket) {
    allClients.push(socket);

    socket.on('disconnect', function() {
        // this is your leaving Socket object
        var index = allClients.indexOf(socket);
        var leaving_socket = allClients[index];

        // this is the way to get the rooms in 1.3.7
        console.log(leaving_socket.rooms);
    }
}

You can check out the documentation here

EDIT

The leaving_socket.rooms is, of course, an array and not a string, since a single socket can be in many rooms at one time. That means you are going to have to loop through that array and find the one you are looking for. A socket is also always in a room that has the same name as the id of the socket.

Dialectician answered 4/12, 2015 at 21:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.