SharedWorker 是唯一支持同源多标签页共享网络连接与统一心跳调度的机制,其核心是将心跳逻辑下沉至 Worker 内部,页面仅通过 postMessage 发送指令和接收通知,配合可见性感知、智能节流及断连兜底策略实现高效协同。

SharedWorker 是目前唯一能在同源多标签页间共享网络连接状态并统一调度心跳的机制。它不依赖单个页面存活,只要任一标签页保持活跃,心跳逻辑就可持续运行,从而避免每个页面各自轮询造成的资源浪费和后台唤醒激增。
核心设计:心跳逻辑下沉到 SharedWorker 内部
所有心跳任务必须完全在 SharedWorker 脚本中实现,页面只负责发送指令(如“开始监控”“切换环境”)和接收状态通知。Worker 内不操作 DOM、不访问 localStorage,仅用 self 和 postMessage 通信。
- 使用 setInterval 发起轻量级心跳请求(如 fetch / WebSocket ping),间隔建议设为 25–45 秒,避开浏览器对后台 tab 的冻结阈值(通常为 60 秒)
- 心跳请求应携带最小必要字段(如
{ type: 'beat', ts: Date.now() }),体积极限控制在 1KB 以内 - 每次请求后必须显式处理响应:成功则更新活跃时间戳;失败则记录错误类型(网络中断、超时、4xx/5xx),不静默忽略
连接状态协同:页面与 Worker 共同维护生命周期
SharedWorker 无法感知页面是否崩溃或冻结,需靠页面主动配合才能精准控制心跳节奏。
- 页面加载后立即通过
worker.port.postMessage({ type: 'init', visibility: document.hidden })向 Worker 报告自身可见性状态 - 监听
visibilitychange,页面切到后台时发送{ type: 'hide' },恢复前台时发{ type: 'show' } - 在
beforeunload或pagehide中调用worker.port.close(),加速 Worker 端清理对应端口,避免无效心跳持续发送
智能节流:按可见性与网络质量动态调整心跳频率
固定间隔心跳在后台场景下既耗电又低效。SharedWorker 可聚合多个页面的状态,实现全站级节流策略。
- Worker 维护一个 Map,记录每个 port 的
lastActive和当前visibility状态 - 当检测到所有接入页面均处于
document.hidden === true且无用户交互超过 30 秒,自动将心跳间隔拉长至 90–120 秒 - 若任意页面触发
visibilitychange回到前台,或收到navigator.onLine === false事件,则暂停心跳 5 秒后以基础间隔重启 - 可选增强:结合
NetworkInformation.effectiveType(如 '2g' / 'slow-2g'),在弱网下延长间隔、减少请求体大小
异常兜底:断连识别与静默恢复
心跳失败不等于连接死亡,需区分临时抖动与真实断连,避免频繁唤醒重试。
- 连续 2 次心跳超时(例如 45 秒未收到响应)才标记为“疑似离线”,不立即重连
- 启动一个 120 秒观察窗口:期间若有任一页面发来业务消息(如登录态刷新、手动触发同步),则视为连接仍有效,重置心跳计时器
- 观察期结束后仍未恢复,再执行指数退避重连(1s → 2s → 4s → 最大 30s),并广播
{ type: 'reconnecting', attempt: n }给所有存活页面 - 重连成功后,向所有 port 补发一次全量状态快照(如最后心跳时间、连接延迟、当前节流模式),确保各页面 UI 一致

















