You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NestJS SocketIO 如何使用disconnecting事件获取客户端断开前的所属房间

问题根因

之前写的逻辑无法拿到客户端房间列表,核心是两点:

  • Nest框架默认重写的handleDisconnect方法,绑定的是SocketIO原生的disconnect事件。这个事件的触发时机,是服务端已经完成客户端与所有房间的解绑流程之后,此时socket实例的房间集合已经被清空,client.rooms自然返回空。
  • SocketIO中socket实例的client.rooms本质是Set结构,并非普通JS对象,控制台直接打印时,经常因为序列化逻辑显示为{},很容易被误判为空集合。

原生SocketIO中可以用来获取完整房间列表的disconnecting事件,触发时机是服务端开始执行解绑客户端与所有房间的流程之前,此时socket的房间集合是完整的,是实现需求的正确时机。

具体实现步骤

Nest目前没有内置针对disconnecting事件的生命周期钩子或装饰器,需要手动在客户端连接流程中绑定对应监听,不需要额外引入复杂逻辑,参考实现如下:

  1. 在你的WebSocket网关类中,保留Nest默认的handleConnection、handleDisconnect方法结构
  2. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.27 10:36:03