页面隐藏时需用visibilitychange停主线程心跳,将心跳与重连移至web worker中执行,并由服务端定时校验连接有效性并兜底关闭超时连接。

页面隐藏时无法靠主线程定时器维持心跳,因为浏览器会冻结或大幅降频 setInterval 和 setTimeout。真正可行的方式是:用 visibilitychange 感知状态切换 + 把心跳逻辑移入 Web Worker + 服务端协同验证连接有效性。
监听 visibilitychange 停止主线程心跳,但不关闭连接
页面切到后台(锁屏、切应用、标签页隐藏)时,document.visibilityState === 'hidden' 会触发。此时应:
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
- 立即清除主线程的心跳定时器(避免无效发包、耗电)
- 不调用
ws.close()—— 系统可能已断开连接,强行 close 会抛InvalidStateError - 不依赖任何主线程的延时任务(如
setTimeout在后台基本不执行)
把心跳和重连逻辑放进 Web Worker
Web Worker 是目前唯一能在 iOS/Android 后台持续运行 JS 的标准机制(Chrome 80+、Firefox 79+、Safari 16.4+ 支持)。Worker 内可:
- 原生创建 WebSocket 实例(同源限制仍存在)
- 使用
setInterval每 25 秒发送{"type":"ping"} - 用
setTimeout监控上一次收到{"type":"pong"}的时间,超 45 秒即判定失联 - 触发重连时采用指数退避:
[1000, 2000, 4000, 8000, 16000],上限不超过 30 秒 - 通过
MessageChannel与主线程通信,转发业务消息,避免主线程挂起导致消息丢失
服务端必须承担连接真实性兜底
前端再努力也无法阻止系统杀进程或网络中断,所以服务端要主动管理连接状态:
- 每次连接建立后,记录该连接的
clientId和last_active_time - 每收到一次心跳或业务消息,更新
last_active_time - 后台定时扫描,对
time.time() - last_active_time > 90的连接主动close() - 不依赖
on_disconnect回调——网络异常时它根本不会触发 - 支持离线摘要推送,用户回到前台时能快速同步错过的关键信息
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










