Socket.io服务端io.emit正常但客户端socket.on事件仅触发一次如何解决
Socket.io
socket.on 仅触发一次问题排查方案 排查步骤
1. 服务端侧校验
- 确认
io.emit发送的内容合法性:在io.emit前打印op字段和tokens[z]的存在性,避免后续z对应的tokens项被意外删除/置空,或者事件名、op字段写错console.log("发送消息,op:", "start", "token是否存在:", !!tokens[z]); io.emit("res",{/* 原有参数 */}) - 新增服务端错误监听,排查发送阶段的隐式错误:
io.on('connection', (socket) => { socket.on('error', (err) => console.error('服务端socket错误:', err)); }); - 校验服务端与客户端Socket.io大版本是否一致,版本不兼容会导致偶发消息丢失。
- 若单次发送的
tokens[z]数据量较大,确认是否超过默认大小限制:Socket.io默认maxHttpBufferSize为1MB,超过的消息会被自动丢弃。
2. 连接状态校验
客户端新增连接状态监听,确认是否存在收完一次消息后自动断连重连的情况:
socket.on('connect', () => console.log('连接成功,socket id:', socket.id)); socket.on('disconnect', (reason) => console.log('连接断开,原因:', reason)); socket.on('connect_error', (err) => console.error('连接出错:', err));
如果日志显示存在重连,说明之前的res事件是绑定在旧的socket实例上,新实例没有绑定监听,自然收不到后续消息。
3. 客户端逻辑校验
- 全局搜索代码中是否存在
socket.off('res')、socket.removeAllListeners()这类移除事件监听的调用,避免误移除了res事件的监听。 - 给
res事件回调新增全局异常捕获,避免回调内部抛出隐式错误导致后续逻辑终止(部分浏览器可能会吞掉异步回调内的未捕获错误):socket.on("res",e=>{ try { // 原有全部回调逻辑 } catch (err) { console.error('res回调执行出错:', err); } }) - 确认收到第一次消息后没有跳转页面、刷新页面的逻辑,导致原有socket实例被销毁。
常见解决方案
- 重连导致的监听失效:将事件绑定逻辑放到
connect回调中,每次重连都重新绑定监听,同时先移除旧监听避免重复触发:
socket.on('connect', () => { socket.off('res'); socket.on('res', e => { /* 原有回调逻辑 */ }); });
- 消息大小超限:调大服务端
maxHttpBufferSize参数:
const io = new Server(server, { maxHttpBufferSize: 1e7 // 调整为10MB,可根据实际业务调整 });
- 版本不兼容:将服务端和客户端Socket.io升级为相同大版本即可。
内容的提问来源于stack exchange,提问作者murmur
相关产品推荐
相关产品推荐

