启用Socket.IO连接状态恢复后Payload格式变为数组的问题
Socket.IO连接状态恢复启用后Payload变为数组的问题
问题现象
启用连接状态恢复功能后,原本通过socket.emit(event, payload)发送的单个对象Payload,客户端接收时变成包含原对象和一个MongoDB文档ID的数组。
原发送的Payload:
{ username: '_id', online: true, lastSeen: '2024-07-17T07:36:19.295Z' }
客户端实际接收内容:
[ { username: '_id', online: true, lastSeen: '2024-07-17T07:36:19.295Z' }, 66979cdf69bcbed06f8f6518 ]
服务端配置
const io = new Server(server, { pingTimeout: 60000, cors: { origin: '*' }, connectionStateRecovery: { // 会话和数据包的备份时长 maxDisconnectionDuration: 2 * 60 * 1000, // 恢复成功后是否跳过中间件 skipMiddlewares: true } });
原因分析
这不是Socket.IO的默认行为,问题出在MongoDB适配器与连接状态恢复功能的兼容性上:启用连接状态恢复后,MongoDB适配器会将待重发的数据包存储到数据库中,恢复过程中重新推送数据时,错误地将数据库文档的_id附加到Payload末尾,导致客户端接收到数组格式的数据。
解决方法
- 客户端临时适配:在接收事件时判断数据格式,若为数组则取第一个元素作为实际Payload:
socket.on('目标事件名', (data) => { const actualPayload = Array.isArray(data) ? data[0] : data; // 后续业务逻辑处理 }); - 升级适配器版本:该问题属于MongoDB适配器的已知兼容性bug,升级到最新版的
socket.io-adapter-mongo即可修复。 - 调整服务端配置:若无需严格的消息重发保障,可暂时禁用连接状态恢复;或自定义恢复逻辑,避免适配器自动附加文档ID。
参考文档内容翻译(原免责声明)
连接状态恢复目前处于实验阶段,后续版本可能会调整API。此外,并非所有第三方适配器都完全支持该功能,使用时可能出现兼容性问题,建议在生产环境中谨慎使用并充分测试。
内容的提问来源于stack exchange,提问作者Adithya Gopakumar
相关产品推荐
相关产品推荐

