Shared Worker 连接状态机必须收束于全局作用域,所有连接状态变量仅定义在 SharedWorkerGlobalScope 顶层;self.onconnect 是唯一可靠入口,需生成 clientId、广播状态、监听端口关闭;WebSocket 管理须覆盖超时、心跳、错误全场景;重连采用指数退避与请求缓存,状态变更需原子广播并带 sequence 号。

Shared Worker 连接状态机必须收束于 Worker 内部
所有连接状态变量(如 ws 实例、readyState、lastPongTime、reconnectDelay、clientIdMap)只能定义在 SharedWorkerGlobalScope 的顶层作用域,不可暴露给页面。页面不得自行 new WebSocket()、setInterval() 或维护心跳计时器——否则多标签页必然状态分裂:A 页面显示“已连接”,B 页面却在重连中;C 页面刚打开就发 subscribe,而连接实际未建立。
状态初始化与端口生命周期绑定
self.onconnect 是唯一可靠的状态机入口,不是消息中继点,而是注册、校验与同步的起点:
- 从 event.ports[0] 获取端口后立即调用 port.start()
- 为该端口生成唯一 clientId(推荐 crypto.randomUUID()),存入 Map 并绑定其生命周期
- 主动广播当前全局状态:{ type: "status", state: currentStatus, sequence: ++seq },避免新页面冷启动时状态缺失
- 监听端口关闭(通过 port.onclose 或定期探测 port.postMessage 报错),及时清理映射表,防止内存泄漏
连接管理需覆盖全生命周期异常场景
WebSocket 的 readyState 有四个值(0–3),但真实断连常发生在非 OPEN 状态下。不能仅靠 onclose 触发重连——它可能在 DNS 失败、TLS 握手超时等连接未真正建立时就触发。必须结合:
- onerror:捕获底层网络或协议错误
- 连接超时控制:new WebSocket() 后若 onopen 未在指定时间(如 8s)内触发,则主动 close() 并标记失败
- 心跳保活:每 30s 发送 ping,服务端需响应 pong;连续 2 次无响应即 ws.close() 并触发重连
- 每次重连前检查:ws?.readyState === WebSocket.CLOSED || ws?.readyState === WebSocket.CONNECTING,防止重复创建实例
重连策略需兼顾稳定性与恢复力
采用指数退避 + 断连隔离设计,避免雪崩和资源耗尽:
- 重连间隔序列:1s → 2s → 4s → 8s → … → 上限 30s
- 所有 WebSocket 回调(onopen/onmessage/onerror)内必须包裹 try/catch,否则未捕获异常会导致整个 Shared Worker 实例崩溃退出
- 断连期间缓存各页面的 subscribe/unsubscribe 请求,重连成功后按序重发
- 状态变更必须原子广播,且带单调递增 sequence 号,供页面做乱序丢弃或幂等渲染

















