web worker 是浏览器后台维持 websocket 长连接并可靠发送心跳的唯一标准化方案,因其不受页面可见性影响,可持续执行连接、ping 发送、超时检测与指数退避重连;主线程仅通过 postmessage 与 worker 通信,worker 负责全量保活逻辑,不兼容时降级为页面级心跳。

Web Worker 与 WebSocket 配合,是目前唯一能在浏览器后台(如切换标签页、锁屏、页面不可见)维持 WebSocket 长连接并可靠发送心跳的标准化方案。
为什么必须用 Worker 管理 WebSocket?
主线程中的 WebSocket 在页面进入后台时极易被浏览器节流甚至冻结:定时器(setInterval)可能暂停、onmessage 延迟触发、send() 失效。而 Web Worker 不受 visibility 状态影响,能持续运行 JS 逻辑,包括创建 WebSocket、发送 ping、检测超时、重连等全部保活动作。
心跳与保活的核心逻辑
不依赖服务端 pong 回复,采用「主动发 + 主动判」策略更稳定:
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
- 每 25 秒调用 ws.send(JSON.stringify({type: 'ping'}))
- 监听 ws.onmessage,收到 {type: 'pong'} 时更新本地 lastPong 时间戳
- 另起一个 setTimeout,每 45 秒检查一次:若 Date.now() - lastPong > 45000,立即 ws.close() 并触发重连
- 重连前加入指数退避:1s → 2s → 4s → 8s… 最大不超过 60 秒
主线程与 Worker 的协作方式
主线程不直接操作 WebSocket,只通过消息通信:
- Worker 初始化后立即 postMessage({type: 'status', connected: false})
- 连接成功后发 {type: 'status', connected: true};断开时发 connected: false
- 所有业务消息(如聊天文本、指令)均由主线程 postMessage({type: 'send', data: xxx}),Worker 负责转发至 ws
- Worker 收到服务端消息后,再 postMessage({type: 'message', payload: xxx}) 通知主线程
兼容性与降级处理
并非所有浏览器都支持 Worker 内原生 WebSocket(如 Safari ≤15.x):
- Worker 启动时尝试 new WebSocket(''),捕获异常则 postMessage({type: 'fallback', reason: 'no_ws_in_worker'})
- 主线程收到 fallback 后,改用页面级保活:监听 document.visibilityState + requestIdleCallback 补发心跳,同时禁用自动重连
- 调试时可在 Chrome DevTools 的 Application → Service Workers 标签下查看 Worker 控制台日志










