Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not able to get the list of rooms the client is currently in on disconnect event #1814

Closed
salvador-dali opened this issue Oct 6, 2014 · 28 comments
Labels
enhancement New feature or request

Comments

@salvador-dali
Copy link

I am trying to find the list of rooms a client is currently in on disconnect event (closes the browsers / reloading the page / internet connection was dropped) and based on my question on SO it looks like it is not possible.

I find it hard to believe that this is the case (I think this is frequently needed functionality). Can any socket.io guru tell whether this is true or even better how can I achieve this?

@yads
Copy link

yads commented Oct 6, 2014

That answer is correct, by the time the 'disconnect' event is emitted the socket has left the rooms. You can either override the onclose handler as suggested or you can store the rooms in whatever mechanism you use for your session store.

@rase-
Copy link
Contributor

rase- commented Oct 6, 2014

Thanks for answering this one, @yads. The disconnect event represents the situation where the socket is "out of the system".

@guille what do you think, should we make some adjustments for this use case?

@barisusakli
Copy link

+1, I would like to inform other users in the same room that someone has disconnected.

So my code would look like :

socket.on('disconnect', function() {
     socket.rooms.forEach(function(room){
         io.in(room).emit('user:disconnect', {id: socket.id});
     });
});

@plessbd
Copy link

plessbd commented Dec 23, 2014

+1 I would also find this useful, however we would also need to make sure this happened before the empty room cleanup happens. Otherwise we run into a case where the room does not exist.

@nkzawa nkzawa added enhancement New feature or request Rooms labels Dec 26, 2014
@X-Coder
Copy link

X-Coder commented Feb 7, 2015

I stumbled across the same situation.

As suggested one dirty workaround is by overriding the the onclose handler.

But it would also work if socket.io would just send something like a "isDisconnecting" event right before the actually cleanup happens. This could be right before the call to this.leaveAll() in the onclose handler happens:

Socket.prototype.onclose = function(reason){
...
  this.emit('disconnecting', reason); //<--insert the new event here
  this.leaveAll();
...
  this.emit('disconnect', reason);
});

(the exports.events array has to be extended by the new eventname to get this working)

Then you can use the new event like this:

  socket.on('disconnecting', function(reason){
    var id = socket.id;
    socket.rooms.forEach(function(room){
      // For each room the user is in, excluding his own room
      if(room != id){
        console.log('Room ' + room + ': a user is disconnecting and leaving this room');
      }
    });
  });

@derikb
Copy link

derikb commented May 1, 2015

+1, this has caused me no end of headaches in my code. It would simplify so much.

@atomicframeworks
Copy link

Just experienced this. Would be nice to have a disconnecting event or something along those lines.

@mattkenefick
Copy link

+1, this is very frustrating

@fydo23
Copy link

fydo23 commented Jun 17, 2015

+1

2 similar comments
@EmilTholin
Copy link

+1

@httnn
Copy link

httnn commented Jul 24, 2015

+1

@shaggybb
Copy link

I have the same problem to solve it. You can develop an in-memory object
where you can save socket.id (or other identifier) with rooms. In
disconnect event you can query this object to know the rooms you have to
leave.

If you are using some DB o NoSQL you can save it for distributed
environments.

Additonally, if rooms list is temporary you can clean it whit controlled
event after disconnecting.

El vie., 24 de julio de 2015 13:44, Max notifications@github.com escribió:

+1


Reply to this email directly or view it on GitHub
#1814 (comment)
.

@ouabing
Copy link

ouabing commented Aug 2, 2015

+1

@frostfang
Copy link

plus elebenty, however did find bodyflex's implementation useful

@Aliance
Copy link

Aliance commented Nov 16, 2015

+1

I tried this solution:

io.on('connection', function(socket) {
    console.log('CONNECT');

    socket.onclose = function(reason) {
        var roomId = socket.rooms[1];
        console.log(roomId);
        Object.getPrototypeOf(this).onclose.call(this, reason);
    }

    // ...
}

And It's works, but I have a feeling that this is not the right way

@abaranovskii
Copy link

+1

@darrachequesne
Copy link
Member

Hi! I suggested here (#2266) adding 'roomJoined' and 'roomLeft' events, would such a solution suit your needs?

server.on('roomJoined', function (id, room) {
  console.log('Socket %s has joined room %s', id, room);
});
server.on('roomLeft', function (id, room) {
  console.log('Socket %s has left room %s', id, room);
});

@X-Coder
Copy link

X-Coder commented Nov 16, 2015

Your suggestion goes a little into a different direction, but will work too.
In my case I would prefer something like a new "disconnecting" event to handle different stuff in one function, when the client is disconnecting. Like in my example I posted in #1814 (comment).

@darrachequesne
Copy link
Member

Well, on second thought, your solution seems cleaner to me. Please note that you may have to clone the array socket.rooms, in order to prevent any race condition:

client.on('disconnecting', function(){
  console.log(client.rooms);
  var clonedRooms = client.rooms.slice();
  setTimeout(function() {
    console.log(client.rooms); // empty array
    console.log(clonedRooms);
  }, 100);
});

@misiek08
Copy link

misiek08 commented Dec 3, 2015

It's a must have feature to have pre-disconnect event. Handling cleanup is much harder without this.

@oskbor
Copy link

oskbor commented Jan 2, 2016

I am currently overriding the onclose handler, would love a solution to this. My override is as simple as emitting the disconnect event before leaving the rooms.

@phutchins
Copy link

I also added a disconnecting event that fires before disconnect and came to submit a PR to find that someone had already submitted a PR with nearly identical code :). +1 for PR #2332 !

@darrachequesne
Copy link
Member

Closed by #2332 👼

@dragosstancu
Copy link

dragosstancu commented May 25, 2020

You don't need to add events, you need to store all the connected sockets into an associative array with keys being the socked IDs. Then, on 'disconnect', you retrieve the room for that socket ID.

let sockets={};
let rooms={};

io.on('connection', function(socket) {
    sockets[socket.id]={
        room:<whatever>
    }

    socket.on('disconnect', (reason) => {
        let room=sockets[socket.id].room;
        io.to(room).emit('message', {
            message: 'I'm out!'
        });
        delete sockets[socket.id];
    });
}

@tribeless
Copy link

Hello everyone, how I was able to solve this was like so:

socket.on(disconnecting,()=>{
const rooms = Object.keys(socket.rooms);
io.to(rooms[1]).emit("event", "message");
});

Thanks, hope it helps someone

laireyx added a commit to ploffer11/WebRTC-Group-Chatting that referenced this issue Jun 8, 2023
laireyx added a commit to ploffer11/WebRTC-Group-Chatting that referenced this issue Jun 8, 2023
@giovanni-bertoncelli
Copy link

giovanni-bertoncelli commented Aug 22, 2023

@darrachequesne I'm trying to use an async function on disconnecting event but probably when the async function gets called the socket.rooms are already emptied... Is there any way to listen to the event with an async listener?

darrachequesne added a commit to socketio/socket.io-website that referenced this issue Sep 4, 2023
@darrachequesne
Copy link
Member

@giovanni-bertoncelli in that case, you will need to create a copy of the socket.rooms set:

io.on("connection", (socket) => {
  socket.on("disconnecting", async (reason) => {
    const rooms = new Set(socket.rooms);

    await someLongRunningOperation();

    // socket.rooms will be empty there
    console.log(rooms);
  });
});

Added here: https://socket.io/docs/v4/server-api/#event-disconnecting

@giovanni-bertoncelli
Copy link

Ok thank you very much!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests