9

我正在尝试查找客户端当前在断开连接事件中所在的房间列表(关闭浏览器/重新加载页面/互联网连接已断开)。

我需要它的原因如下:用户进入了几个房间。然后其他人也做了同样的事情。然后他关闭浏览器选项卡。我想通知他离开的房间里的所有人。

所以我需要在“断开连接”事件中做一些事情。

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

  });
});

我已经尝试了两种方法,发现它们都是错误的:

1)遍历adapter.rooms.

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

这是错误的,因为适配器房间有所有房间。不仅是我的客户所在的房间。

2)经过client.rooms。这将返回客户端所在房间的正确列表,但在断开连接事件时不返回。断开连接时,此列表已为空[]

那么我该怎么做呢?在撰写本文时,我正在使用最新的socket.io:1.1.0

4

2 回答 2

17

默认情况下这是不可能的。查看 socket.io 的源代码。

那里有在回调Socket.prototype.onclose之前执行的方法。socket.on('disconnect',..)所以在那之前所有的房间都被留下了。

/**
 * 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);
};

解决方案可能是破解 socket.js 库代码或覆盖此方法,然后调用原始方法。我很快测试了它似乎工作:

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);
}
于 2014-09-16T08:37:50.123 回答
11

我知道,这是一个老问题,但在当前版本的 socket.io 中,有一个在断开连接之前运行的事件,您可以访问他加入的房间列表。

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

也可以看看:

服务器 API 文档 - “断开连接”事件

于 2016-10-12T17:43:06.883 回答