websocket断网重连需保障消息不丢、有序、不重复:1.拦截发送并入队缓存;2.心跳检测+退避重连防雪崩;3.重连后逐条限速重发并支持ack确认;4.监听页面生命周期清理资源。

WebSocket 断网后自动重连本身不难,但要“带队列”——即断线期间发出去的消息不丢、按序重发、且不重复——需要协调连接状态、消息缓存、重连策略和发送节奏。核心是:**连接未就绪时不直接 send,而是暂存;连接恢复后按顺序重放;重连过程需防雪崩、防重复、防内存泄漏。**
1. 消息拦截与本地队列管理
所有发送操作必须绕过原生 ws.send(),统一走自定义发送函数:
- 若 WebSocket 状态为
OPEN(1),直接发送; - 若为
CLOSING(2)或CLOSED(0),把消息(含类型、数据、时间戳、唯一 ID)推入一个数组队列(如this.sendQueue = []); - 避免存大对象或闭包,只存可序列化的纯数据(必要时用
JSON.stringify预处理); - 可加长度限制(如最多缓存 100 条),超限时丢弃最老消息或报错提示。
2. 连接状态监控与可控重连机制
不能依赖 onclose 就立刻重连,需结合心跳 + 超时判断是否真断连:
- 启动定时心跳(如每 25s 发
ping消息),服务端回pong; - 连续 2 次心跳无响应,视为断连,触发
reconnect(); - 重连使用退避策略:首次延时 1s,失败则 2s → 4s → 8s,上限建议 30s,避免高频请求压垮服务端;
- 设置最大重试次数(如 10 次),超限后暂停自动重连,暴露错误供上层处理(如弹提示、降级为轮询)。
3. 重连成功后安全重发队列
不是简单遍历队列 send,要注意三点:
- 重连成功(
onopen触发)后,先清空旧监听器、重置心跳定时器,再开始重发; - 逐条发送,每发一条后加微小间隔(如
await new Promise(r => setTimeout(r, 16))),防止瞬间涌出导致服务端限流或乱序; - 对关键消息(如订单提交),可要求服务端返回 ACK,客户端收到后才从队列中移除;未确认的保留,下次重连继续发(需服务端幂等支持);
- 重发前检查队列是否已被清空(比如用户主动断开或页面卸载),避免误发。
4. 页面生命周期与资源清理
避免后台标签页或关闭前堆积无效队列:
- 监听
beforeunload或pagehide,尝试同步发送剩余队列(仅限轻量、非关键消息),或持久化到localStorage(注意大小限制); - 页面重新可见(
visibilitychange)时,若连接已断,立即触发重连; - 每次新建 WebSocket 实例后,记得清除旧的
onmessage/onerror等引用,防止内存泄漏; - 提供
destroy()方法,手动清空队列、关闭连接、取消定时器,便于组件卸载时调用。
不复杂但容易忽略细节。重点不在“重连”,而在“重连时消息不乱、不丢、不炸”。实际项目中,建议封装成 Class(如 ReconnectableSocket),把队列、状态、退避、心跳都内聚管理,上层只关心 send() 和 onmessage。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











