Socket IO客户端重连后无法接收事件的问题解决
Socket.IO单例重连后组件事件不触发的解决方法
问题原因
Socket.IO客户端断开重连后,原连接会话的事件处理器不会自动关联到新的连接会话上。你当前的组件仅在挂载时绑定一次事件,重连后事件监听自然失效。
解决方案1:封装单例的订阅/取消订阅方法(推荐)
修改socket_io.js,维护事件订阅列表,在重连时自动重新绑定所有订阅的事件:
import EndPoints from './http/endpoints'; import io from "socket.io-client"; const socketUrl = EndPoints.SOCKET_BASE; const socketOptions = { transports: ["websocket"] }; let socket; // 存储每个事件对应的回调函数集合 const eventSubscriptions = new Map(); function initSocket() { socket = io(socketUrl, socketOptions); socket.on('connect', () => { console.log(`Connected to Server`); // 重连后重新绑定所有已订阅的事件 eventSubscriptions.forEach((callbacks, eventName) => { callbacks.forEach(callback => socket.on(eventName, callback)); }); }); socket.on('disconnect', () => { console.log(`Disconnected from Server`); // 断开时移除所有事件绑定,避免重连后重复触发 eventSubscriptions.forEach((_, eventName) => socket.off(eventName)); }); } // 订阅事件 export function subscribe(eventName, callback) { if (!socket) initSocket(); if (!eventSubscriptions.has(eventName)) { eventSubscriptions.set(eventName, new Set()); } eventSubscriptions.get(eventName).add(callback); // 立即绑定事件 socket.on(eventName, callback); } // 取消订阅事件 export function unsubscribe(eventName, callback) { if (!socket || !eventSubscriptions.has(eventName)) return; const callbacks = eventSubscriptions.get(eventName); callbacks.delete(callback); socket.off(eventName, callback); // 清理空的事件集合 if (callbacks.size === 0) { eventSubscriptions.delete(eventName); } } export default socket;
在组件中使用:
import { subscribe, unsubscribe } from '../socket_io.js'; const MessagePage = () => { const messageHandler = (data) => { // 处理消息逻辑 }; useEffect(() => { subscribe('message', messageHandler); return () => unsubscribe('message', messageHandler); }, []); return ( // 组件内容 ); };
解决方案2:在组件中监听重连事件手动绑定
无需修改单例文件,在组件的useEffect中监听socket的connect事件,每次连接(包括重连)时重新绑定事件:
import socket from '../socket_io.js'; const MessagePage = () => { const messageHandler = (data) => { // 处理消息逻辑 }; useEffect(() => { // 绑定/解绑事件的辅助函数 const bindMessageEvent = () => socket.on('message', messageHandler); const unbindMessageEvent = () => socket.off('message', messageHandler); // 初始绑定 bindMessageEvent(); // 重连时重新绑定,断开时解绑避免重复绑定 socket.on('connect', bindMessageEvent); socket.on('disconnect', unbindMessageEvent); // 组件卸载时清理所有监听 return () => { unbindMessageEvent(); socket.off('connect', bindMessageEvent); socket.off('disconnect', unbindMessageEvent); }; }, []); return ( // 组件内容 ); };
说明
方案1更适合多组件共用Socket.IO的场景,统一管理事件订阅,避免每个组件重复处理重连逻辑;方案2适合快速修复单个组件的问题,无需修改单例文件。
内容的提问来源于stack exchange,提问作者ololo
相关产品推荐
相关产品推荐

