Get the list of rooms the client is currently in o

2019-02-13 02:33发布

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).

I need it for the following reason: user has entered few rooms. Then other people has done the same. Then he closes a browser tab. And I want to notify all the people in the rooms he is in that he left.

So I need to do something inside of on 'disconnect' event.

io.sockets.on('connection', function(client){
  ...
  client.on('disconnect', function(){

  });
});

I already tried two approaches and found that both of them are wrong:

1) iterating through adapter.rooms.

for (room in client.adapter.rooms){
   io.sockets.in(room).emit('userDisconnected', UID);
 }

This is wrong, because adapter rooms has all rooms. Not only the rooms my client is in.

2) Going through client.rooms. This returns a correct list of rooms the client is in, but no on the disconnect event. On disconnect this list is already empty [].

So how can I do it? I am using the latest socket.io at the time of writing: 1.1.0

2条回答
啃猪蹄的小仙女
2楼-- · 2019-02-13 02:56

I know, it's an old question, but in the current version o socket.io there is a event that runs before disconnect that you can access the list of the rooms he joined.

client.on('disconnecting', function(){
    Object.keys(socket.rooms).forEach(function(roomName){
        console.log("Do something to room");
    });
});

https://github.com/socketio/socket.io/issues/1814

See also:

Server API documentation - 'disconnecting' event

查看更多
贼婆χ
3楼-- · 2019-02-13 02:59

This is not possible by default. Have a look at the source code of socket.io.

There you have the method Socket.prototype.onclose which is executed before the socket.on('disconnect',..) callback. So all rooms are left before that.

/**
 * Called upon closing. Called by `Client`.
 *
 * @param {String} reason
 * @api private
 */

Socket.prototype.onclose = function(reason){
  if (!this.connected) return this;
  debug('closing socket - reason %s', reason);
  this.leaveAll();
  this.nsp.remove(this);
  this.client.remove(this);
  this.connected = false;
  this.disconnected = true;
  delete this.nsp.connected[this.id];
  this.emit('disconnect', reason);
};

A solution could be either to hack the socket.js library code or to overwrite this method and then call the original one. I tested it pretty quick at it seems to work:

socket.onclose = function(reason){
    //emit to rooms here
    //acceess socket.adapter.sids[socket.id] to get all rooms for the socket
    console.log(socket.adapter.sids[socket.id]);
    Object.getPrototypeOf(this).onclose.call(this,reason);
}
查看更多
登录 后发表回答