重连、错误处理与清理
妥善处理断开连接,并在 useEffect 中清理套接字监听器。
重连、错误处理与清理 是 CoddyKit 上的免费 React Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 React Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 React Academy 课程共包含 4 节课。
为什么重连很重要
移动设备上经常发生网络中断。如果没有重连逻辑,用户会在不知不觉中失去实时连接。好的策略是结合退避机制自动重试。
Socket.IO 自动重连
Socket.IO 默认会自动重连。请在 io() 选项中配置 reconnectionAttempts、reconnectionDelay 和 reconnectionDelayMax。
const socket = io('https://api.example.com', {
reconnectionAttempts: 5,
reconnectionDelay: 1000, // initial delay
reconnectionDelayMax: 10000, // max delay (exponential backoff)
randomizationFactor: 0.5,
});在 React 中跟踪连接状态
监听 connect、disconnect 和 connect_error 事件,并将状态反映到组件状态中。
function useConnectionStatus() {
const [status, setStatus] = useState<'connected' | 'disconnected' | 'error'>(
socket.connected ? 'connected' : 'disconnected'
);
useEffect(() => {
socket.on('connect', () => setStatus('connected'));
socket.on('disconnect', () => setStatus('disconnected'));
socket.on('connect_error', () => setStatus('error'));
return () => {
socket.off('connect');
socket.off('disconnect');
socket.off('connect_error');
};
}, []);
return status;
}显示重连提示条
套接字断开连接时显示提示条,让用户知道自己处于离线状态且正在重新连接。
function ConnectionBanner() {
const status = useConnectionStatus();
if (status === 'connected') return null;
return (
<div className="banner warning">
{status === 'error' ? 'Connection failed' : 'Reconnecting...'}
</div>
);
}手动重连
重试次数耗尽后,让用户通过按钮触发手动重连。
const [failed, setFailed] = useState(false);
socket.on('reconnect_failed', () => setFailed(true));
if (failed) {
return (
<button onClick={() => { setFailed(false); socket.connect(); }}>
Retry connection
</button>
);
}原生 WebSocket 重连
原生 WebSocket 没有内置重连功能。请手动实现指数退避:连接关闭后,等待 Math.min(delay * 2, maxDelay),再尝试建立新连接。
function connectWithBackoff(url, attempt = 0) {
const ws = new WebSocket(url);
ws.onclose = () => {
const delay = Math.min(1000 * 2 ** attempt, 30000);
setTimeout(() => connectWithBackoff(url, attempt + 1), delay);
};
return ws;
}在 useEffect 中进行清理
在 useEffect 中添加的每个套接字监听器,都必须在清理函数中移除。未这样做会导致内存泄漏和重复的事件处理。
useEffect(() => {
const onData = (d) => setState(d);
socket.on('data', onData);
return () => {
socket.off('data', onData); // remove specific handler reference
};
}, []);避免处理程序中的陈旧闭包
当套接字处理程序引用状态或属性时,它会捕获陈旧闭包。请使用引用始终访问最新值。
const handlerRef = useRef(null);
handlerRef.current = (msg) => updateMessages(messages, msg); // fresh ref each render
useEffect(() => {
const onMsg = (...args) => handlerRef.current(...args);
socket.on('message', onMsg);
return () => socket.off('message', onMsg);
}, []); // no deps needed重连时发送待处理消息
断开连接时将传出消息加入 queue,并在连接重新建立后清空 queue。
const queue = useRef<string[]>([]);
socket.on('connect', () => {
while (queue.current.length) {
socket.emit('message', queue.current.shift());
}
});
function send(text: string) {
if (socket.connected) socket.emit('message', text);
else queue.current.push(text);
}重连后重新加入房间
Socket.IO 会在断开连接时清除房间成员关系。套接字重连后重新加入房间,以恢复订阅。
useEffect(() => {
function rejoin() { socket.emit('join-room', roomId); }
socket.on('connect', rejoin);
return () => socket.off('connect', rejoin);
}, [roomId]);全局错误处理
妥善处理无法恢复的错误:显示错误界面,并将重新加载页面作为最后的应对措施。
socket.on('connect_error', (err) => {
console.error('Socket error:', err.message);
// Show user-friendly error
});快速检查
在 useEffect 清理过程中不移除套接字事件监听器,会有什么风险?
要点回顾
使用退避选项配置 Socket.IO 重连。在 React 状态中反映连接状态,显示重连提示条,重连后重新加入房间,并始终在 useEffect 清理过程中移除监听器。离线时将待处理消息加入队列,并在重连后发送。
常见问题解答
「重连、错误处理与清理」课时是免费的吗?
是的 — 「重连、错误处理与清理」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 React Academy 课程的其余内容,请升级到 CoddyKit PRO。 React Academy 课程共包含 4 节课。
「重连、错误处理与清理」这节课中我会学到什么?
妥善处理断开连接,并在 useEffect 中清理套接字监听器。 你通过在浏览器中直接运行的动手代码来练习 React Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 React Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 React Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「重连、错误处理与清理」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 React Academy 课中编写并运行代码吗?
能。每节 React Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。