NestJS SocketIO 如何使用disconnecting事件获取客户端断开前的所属房间
问题根因
之前写的逻辑无法拿到客户端房间列表,核心是两点:
- Nest框架默认重写的
handleDisconnect方法,绑定的是SocketIO原生的disconnect事件。这个事件的触发时机,是服务端已经完成客户端与所有房间的解绑流程之后,此时socket实例的房间集合已经被清空,client.rooms自然返回空。 - SocketIO中socket实例的
client.rooms本质是Set结构,并非普通JS对象,控制台直接打印时,经常因为序列化逻辑显示为{},很容易被误判为空集合。
原生SocketIO中可以用来获取完整房间列表的disconnecting事件,触发时机是服务端开始执行解绑客户端与所有房间的流程之前,此时socket的房间集合是完整的,是实现需求的正确时机。
具体实现步骤
Nest目前没有内置针对disconnecting事件的生命周期钩子或装饰器,需要手动在客户端连接流程中绑定对应监听,不需要额外引入复杂逻辑,参考实现如下:
- 在你的WebSocket网关类中,保留Nest默认的
handleConnection、handleDisconnect方法结构 - 在
handleConnection(客户端连接成功时自动触发的方法)内部,直接为当前连接的socket实例绑定disconnecting事件的处理逻辑
示例代码:
import { WebSocketGateway } from '@nestjs/websockets'; import { Socket } from 'socket.io'; @WebSocketGateway({ cors: { origin: '*' } }) export class ChatRoomGateway { // 客户端连接成功时自动触发 handleConnection(client: Socket) { // 为当前socket手动绑定disconnecting事件监听 client.on('disconnecting', () => { // client.rooms是Set结构,转成数组才能拿到完整的房间列表 const allRoomsOfClient = Array.from(client.rooms); // 在此处编写对应的业务逻辑,例如: // - 遍历所有所属房间,向剩余在线用户推送该客户端的离线通知 // - 同步该客户端的离线状态到对应房间 console.log('客户端断开前的所有所属房间:', allRoomsOfClient); }); } // 该方法绑定disconnect事件,触发时房间集合已清空,不适合做房间相关逻辑 handleDisconnect(client: Socket) { // 此处的client.rooms为空集合,不要在这里获取房间列表 } }
注意事项
- 不要尝试在
handleDisconnect方法中获取房间列表:事件触发时机过晚,集合已经被清空,无法拿到有效数据 - 不要直接对
client.rooms做JSON序列化、或者按对象属性读取:它是Set结构,必须通过Array.from()转成数组后再使用,否则会出现集合明明有值,但读出为空的问题 - 不需要在网关的
afterInit钩子里额外监听服务端的全局connection事件:直接在Nest自动触发的handleConnection里绑定监听,是最简洁、不会出现重复绑定的实现方式
内容的提问来源于stack exchange,提问作者Minh Thùy Phạm
相关产品推荐
相关产品推荐

