navigator.onLine不可靠,因其仅反映操作系统网络接口启用状态,无法判断真实互联网连通性;需结合online/offline事件监听与fetch健康探测(如/health)验证业务可达性。

navigator.onLine 只能读取瞬时状态,不能替代事件监听;online/offline 事件必须绑定到 window,且需配合健康请求验证真实连通性。
为什么不能只靠 navigator.onLine 判断是否真能上网
该属性返回的是操作系统上报的“网络接口是否启用”,不是“能否访问你的服务器”。常见误判场景包括:
- Wi-Fi 已连但路由器断网 →
navigator.onLine仍为true - 公司内网可通但外网被墙 →
navigator.onLine为true,但fetch('/api')必然失败 - Android WebView 中该值长期不更新,甚至始终为
true -
file://协议下恒为true,无法用于本地开发测试
window.addEventListener('online') 和 offline 的实际行为
这两个事件由浏览器引擎触发,但响应有延迟或丢失风险:
- Chrome/Edge 通常在系统网络栈切换后 1–3 秒内触发,但无保证
- iOS Safari 在后台标签页中可能完全不触发
offline - 安卓 WebView(尤其旧版)常漏掉首次离线事件,需手动补一次探测
- 事件不可取消,也无法阻止用户“掉线”——只能做响应式处理
- 不要用
window.ononline = handler,它会覆盖其他模块注册的同名监听器
如何让网络状态判断真正可靠
仅监听事件 + 读属性是脆弱的。必须加入轻量级主动探测:
立即学习“前端免费学习笔记(深入)”;
- 在
online回调里立即发起一次fetch('/health', { method: 'HEAD', cache: 'no-store', signal: AbortSignal.timeout(1500) }) - 成功(2xx)才认为“真在线”,恢复同步、重试队列等逻辑
- 失败(网络错误、超时、非 2xx)则维持离线 UI,不执行依赖网络的操作
- 避免高频探测:只在状态切换后触发一次,或用户手动点击“重试”时再发
- 健康接口应返回极小响应体(如空 body + 200),不带 Cookie 或认证头,减少干扰
测试时别信拔网线,用 DevTools 离线模式
物理断网在多网卡、虚拟机、企业防火墙环境下经常不生效,navigator.onLine 不变是常态:
- Chrome / Edge:F12 → Network tab → 勾选
Offline - Firefox:F12 → Network tab → 点击左上角飞机图标
- 此方式由浏览器直接拦截所有网络请求,
navigator.onLine强制变为false,事件必触发 - 务必关闭页面再重开测试 —— 部分浏览器在离线状态下加载的页面,
navigator.onLine仍为true
最易被忽略的一点:事件监听器必须在页面生命周期早期注册,且不能漏掉清理。若用 React,useEffect 的 cleanup 函数里要调用 removeEventListener;若纯 JS,应在 beforeunload 时移除,否则可能引发内存泄漏或重复回调。



















