必须在 send() 前双重校验:ws.readystate === websocket.open 且最近心跳响应未超时;仅靠 readystate 或 navigator.online 不可靠,真实健康需通过定时 ping/pong 与业务消息时间戳联合验证。

发送消息前必须确认连接真正可用,不能只看 readyState === 1,也不能依赖 navigator.onLine。健康状态需要通信行为验证,而非静态值判断。
只认 WebSocket.OPEN 不等于连接健康
readyState === WebSocket.OPEN 仅表示握手完成、通道已建立,不代表当前能收发数据。网络中断、防火墙拦截、中间设备静默断连后,该值可能维持数秒甚至更久不变——此时调用 send() 看似成功,实则消息已丢失。
- 务必在
send()前做双重校验:先检查ws.readyState === WebSocket.OPEN,再确认最近一次心跳响应未超时 - 避免直接写
if (ws.readyState)或if (ws.readyState === 1),旧版 WebView 可能不支持常量,且易忽略状态语义 - 构造 WebSocket 实例后立即读 readyState 几乎总是 0,不能用于判断是否可发消息
靠心跳响应判断真实连通性
健康 = 客户端发出 ping 后,服务端在约定时间内返回 pong。这是唯一能反映底层链路是否通畅的信号。
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
- 客户端定时发原生
ping帧(非 JSON 字符串),启动超时计时器 - 监听
ws.on('pong'),收到即清除超时计时器 - 超时未收到 pong,说明连接已失效,应主动
ws.close(4999, 'heartbeat timeout') - 服务端若不响应标准 PONG 帧(如只处理业务消息),心跳机制即失效,需推动服务端修复
结合业务消息时间戳交叉验证
仅靠协议心跳不够——它保的是 TCP 层,不是业务层。如果服务端卡住、消息堆积或鉴权未完成,pong 正常但业务消息停滞。
- 为每条关键业务消息(如行情 tick、ACK)打时间戳,记录最后接收时间
- 设置业务层空闲阈值(如 15 秒无新消息),超过即触发重连或告警
- onmessage 中更新时间戳,避免因消息格式错误或解析失败导致误判
- 业务消息和心跳响应需独立计时,任一超时都视为连接异常
错误事件与关闭码是关键线索
onerror 和 onclose 是连接异常的唯一直接出口,必须捕获并解析细节。
-
onerror在连接失败或传输错误时触发,常伴随readyState === 0,是重连起点 -
onclose中读取event.code:1000 表示正常关闭;1006 是异常断开(如网络中断);1013 建议重试 - 不要忽略
event.reason,部分服务端会附带断连原因(如 "idle timeout") - 所有 send 失败应降级为日志+重试队列,而非抛错阻塞流程










