WebSocket断开后自动重连并重发未确认消息需三步:状态管理(isConnected标志与reconnectCount计数器)、重连策略(指数退避延时+最大5次限制)、消息缓存与去重(pendingMessages队列+msgId幂等+status状态机+online事件+心跳检测)。

WebSocket 断开后自动重连并重发未确认消息,关键在于三件事:状态管理、重连策略、消息缓存与去重。不能只简单地 onclose 里 new WebSocket(),否则会丢消息、无限重连或重复发送。
用变量跟踪连接状态和重连尝试次数
定义一个标志位(如 isConnected)和计数器(如 reconnectCount),在 onopen/onclose/onerror 中及时更新。每次断开时递增计数器,并限制最大重试次数(比如 5 次),避免雪崩式重连。超过阈值可暂停或降级为轮询提示用户。
- onopen → 设置 isConnected = true,重置 reconnectCount = 0
- onclose / onerror → 设置 isConnected = false,reconnectCount++,然后调用重连函数
- 重连前加延时(如 1s 初次,指数退避到最多 30s),避免瞬间密集请求
缓存待发送消息并标记“需确认”
所有调用 send() 的消息,先不直接发,而是推入一个队列(如 pendingMessages),每条带唯一 ID 和时间戳。只在 WebSocket readyState === 1(OPEN)且 isConnected === true 时才批量/逐条发送。发送后暂不移除,等收到服务端 ACK 后再清理。
详细的 Three.js 3D 图形参考,涵盖场景设置、相机、几何体、材质、光照、动画、控制器、加载器、数学工具和调试。
- 服务端需支持业务 ACK(例如 { "type": "ack", "msgId": "abc123" })
- 前端监听消息,匹配 msgId,成功则从 pendingMessages 中删除对应项
- 重连成功后,遍历 pendingMessages 全部重发(可加已发送标记避免重复)
防止重连期间重复发送同一消息
仅靠重发 pending 队列还不够——如果重连成功前某条消息其实已发出但没收到 ACK,重连后又发一遍,就会重复。解决方案是:服务端做幂等处理(用 msgId 去重),前端配合加“已提交但未确认”状态。
立即学习“Java免费学习笔记(深入)”;
- 每条消息生成全局唯一 msgId(如 Date.now() + Math.random().toString(36).substr(2, 9))
- 发送前设 status = 'sent-pending';收到 ACK 改为 'confirmed';超时未回改为 'timeout'(可人工干预)
- 重连后只重发 status === 'sent-pending' 的消息,跳过 'confirmed' 或 'timeout'(后者可单独重试)
监听网络恢复并触发快速重连
单纯依赖 onclose 不够,比如弱网下连接卡住但没触发 close。应监听 window.online/offline 事件,在网络恢复时主动检查连接状态,若已断开则立即触发重连逻辑。
- addEventListener('online', () => { if (!isConnected) tryReconnect(); })
- 搭配心跳检测(如每 30s send({ type: 'ping' }),超时 5s 无 pong 则视为断连)更可靠
- 心跳响应也走 ACK 机制,统一进 pending 队列管理

















