navigator.onLine 不可靠,因它仅监听系统网络接口状态而无法检测实际网络可达性,常见误判包括连局域网无外网、DNS失败、Chrome启动瞬时假在线、旧Android WebView恒返回true。

navigator.onLine 只能告诉你浏览器“认为”自己在线,不能代表真能访问服务器——比如路由器断了、DNS 挂了、代理失效时,它仍可能返回 true。要真正判断用户能否连通后端,必须发请求验证。
为什么 navigator.onLine 不可靠?
它只监听操作系统网络接口(如 Wi-Fi 开关、网卡启用状态),不检测网络可达性。常见误判场景包括:
- 连上了局域网热点但没外网
- 系统报告“已连接”,但 DNS 解析失败
- Chrome 启动瞬间
navigator.onLine初始值为true,实际尚未联网 - 旧版 Android WebView(尤其 Cordova)始终返回
true
用 fetch() 做轻量探测才是关键
推荐对一个你完全可控的 endpoint 发起 HEAD 请求,比如 /favicon.ico 或专门的健康检查路径 /health。它体积小、无副作用、缓存可控。
实操要点:
立即学习“前端免费学习笔记(深入)”;
- 加
cache: 'no-store'防止强缓存干扰判断 - 用
AbortController设超时(建议 3–5 秒),避免请求卡死 - 把
404当作“网络可达”信号(说明服务端响应了,只是资源不存在) - 不要依赖
response.ok,而应优先看是否拿到响应(catch或signal.aborted才是断网核心指标)
示例片段:
function checkNetwork() {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 3000);
return fetch('/favicon.ico', {
method: 'HEAD',
cache: 'no-store',
signal: controller.signal
})
.then(res => {
clearTimeout(timeoutId);
return res.status === 404 || res.ok;
})
.catch(() => false);
}
监听 online/offline 事件只能辅助,不能替代探测
这两个事件响应快,适合 UI 状态切换(比如禁用提交按钮、显示“离线中”提示),但它们触发时机滞后且不准:
-
offline事件可能在真实断网后延迟数秒才触发 -
online事件可能在 DNS 恢复前就触发,导致 UI 提前变绿 - 页面刚加载时,事件尚未触发,
navigator.onLine的初始值不可信
所以正确做法是:页面加载后立即执行一次 checkNetwork(),再结合事件做后续更新;不要只靠事件初始化状态。
最易被忽略的一点:网络探测必须和业务请求共用同一域名与协议(同源),否则跨域预检失败会误判为断网;如果后端部署在子路径或有反向代理,探测地址也要严格匹配其可访问路径。


















