es6 class封装websocket自动重连需以状态机为核心,维护connecting/open/closing/closed/reconnecting五态,配合isreconnecting标志与wsref缓存;采用指数退避(1s起翻倍)、最大重试5次、页面隐藏暂停重连;独立心跳机制每30s发ping,2次无pong则主动关闭;onclose依code(1000不重连、1006重连、≥4000按业务处理)和wasclean决策,所有操作延时执行防报错。

用ES6 class封装高性能WebSocket自动重连,关键不在“新建连接”,而在“状态可控、资源干净、探测主动、退避合理”。硬写 onclose → connect() 会快速崩掉,必须用状态机兜住整个生命周期。
定义清晰的内部状态与生命周期控制
别依赖 readyState 做决策——它滞后、不可靠(比如NAT超时后仍显示 OPEN)。你需要自己维护细粒度状态:
- CONNECTING:开始 new WebSocket,但尚未触发 onopen
- OPEN:已建立通信,可收发消息
- CLOSING:正在关闭中(如调用了 close())
- CLOSED:已彻底断开,无残留实例
- RECONNECTING:进入重连流程,用于拦截重复触发
配套用布尔标志 isReconnecting 和引用缓存 wsRef:每次重连前先 wsRef?.close() 并置为 null,避免旧实例监听器堆积、定时器残留。
指数退避重连 + 可控重试次数
固定间隔重试(如每2秒试一次)在弱网下极易被服务端限流或拒绝。应实现指数退避:
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
- 初始延迟 1000ms,失败后翻倍(2000ms → 4000ms → 8000ms…)
- 设置最大重试次数(如 5 次),超过后暂停或上报告警
- 重连前清空上一轮的
reconnectTimer和heartbeatTimer - 页面隐藏(
document.hidden)时暂停重连计时,恢复后再继续
独立心跳机制 + 主动超时判定
仅靠 onclose 不够——TCP 层“假连接”时事件不触发,但 send 已失效。心跳必须是主动探测:
- 连接成功后启动
setInterval发送{"type":"ping"},间隔 ≤30s(避开 Nginx 默认 60s 超时) - 每次发 ping 前
clearTimeout(heartbeatTimeout),收到{"type":"pong"}后重置超时计时器 - 连续 2 次未响应(即 60 秒内无 pong),主动
ws.close(4999, "no_pong")强制触发 onclose 流程 - 心跳逻辑绑定到当前 ws 实例,每次重连后重建,绝不复用旧定时器
onclose 决策必须区分 code 与上下文
onerror 是哑事件,不能作为重连依据;真正可靠的是 onclose 的 event.code 和 event.wasClean:
-
code === 1000:正常关闭(如用户登出),不重连 -
code === 1006:异常关闭(如网络中断),立即启动重连 -
code >= 4000:业务自定义码,需按语义处理(如 4001 表示 token 过期,应刷新凭证再连) -
wasClean === false:非主动关闭,大概率需重连
所有重连动作必须包裹在 setTimeout 中延时执行,确保旧实例资源已释放,避免 WebSocket is already CLOSED 报错。










