使用 Map + Set 管理 WebSocket 房间连接,以字符串 roomId 为键、Set 为值,实现 O(1) 查找与去重;需在连接关闭时调用 leaveRoom 清理,避免内存泄漏。

用 Map 管理 WebSocket 房间连接,核心是把房间 ID 作为键(string 或 number),对应值设为该房间内所有客户端连接(如 Set 或 Array)。这样通过 map.get(roomId) 就能 O(1) 时间复杂度 拿到连接集合,无需遍历。
用 Map + Set 存储连接,保证去重和高效操作
Set 天然适合存 WebSocket 实例——自动去重、支持快速增删、不关心顺序。配合 Map,结构清晰且性能好:
- 创建:
const rooms = new Map>(); - 加入房间:
如果房间不存在,先初始化空 Set;再 add 当前连接if (!rooms.has(roomId)) rooms.set(roomId, new Set());<br>rooms.get(roomId)!.add(ws);
- 离开房间:
const clients = rooms.get(roomId);<br>if (clients) { clients.delete(ws); if (clients.size === 0) rooms.delete(roomId); }
用字符串房间 ID 作键,避免隐式类型转换问题
WebSocket 传来的房间 ID 通常是字符串(如 URL 查询参数或 JSON 消息中的 "room-123"),直接用它作 Map 键最安全。不要用数字强制转换(如 +roomId),否则可能因 "123" 和 123 被视为不同键导致数据错乱。
- 推荐写法:
const roomId = data.roomId; // 假设是 string - 谨慎处理:
parseInt()或Number()后的值不能混用于同一 Map 的键 - 调试时可用
console.log([...rooms.keys()])查看实际键类型
广播消息时直接 get + forEach,无须查找过滤
向某房间所有人发消息,只需三步:取集合 → 遍历 → 发送。没有循环所有连接再判断房间 ID 的开销:
const clients = rooms.get(roomId);if (clients) {<br> for (const client of clients) {<br> if (client.readyState === WebSocket.OPEN) {<br> client.send(JSON.stringify(msg));<br> }<br> }<br>}- 注意检查
readyState,避免向已断开连接发送失败报错
清理断开连接,防止内存泄漏
WebSocket 关闭时必须从对应房间 Set 中移除,否则连接对象无法被 GC,长期运行会内存溢出:
- 在
ws.on('close', ...)或ws.onclose回调中执行清理 - 可封装一个通用函数:
function leaveRoom(ws: WebSocket, roomId: string) {<br> const clients = rooms.get(roomId);<br> if (clients) { clients.delete(ws); if (clients.size === 0) rooms.delete(roomId); }<br>} - 建议给每个连接绑定
roomId属性(如ws.roomId = roomId),便于关闭时反查
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











