navigator.onLine 仅反映浏览器对网络接口的粗略感知,无法准确判断真实连通性;需结合主动探测(如 fetch /healthz)和错误捕获才能可靠识别离线状态。

navigator.onLine 的判断逻辑和真实网络状态不一致
navigator.onLine 只反映浏览器是否认为自己“在线”,它不发任何网络请求,也不检查 DNS、代理或服务器连通性。Chrome/Firefox 在系统网络接口关闭(如禁用 Wi-Fi)时返回 false,但一旦有任意本地网络(比如仅连接到一个没网的路由器),就立刻返回 true。这意味着用户看到“已连接”提示,却实际打不开页面——这是最常被误用的根源。
所以不能只靠 navigator.onLine 做唯一判断。它适合快速响应「明显断网」场景(比如拔掉网线瞬间),但必须搭配主动探测才能确认真实可用性。
监听 online/offline 事件时容易漏掉初始状态
页面加载时,navigator.onLine 已有值,但 online 或 offline 事件不会自动触发。如果用户打开页面时就断网,你没做初始化检查,提示框永远不会出现。
实操建议:
- 页面加载后立即检查
navigator.onLine,并据此显示/隐藏离线提示 - 用
window.addEventListener('online', handler)和window.addEventListener('offline', handler)监听切换 - 避免用
window.ononline这类旧式属性赋值,它会被后续监听器覆盖
单纯依赖 navigator.onLine 显示提示会误导用户
用户真正需要知道的是:“我当前能否提交表单/加载图片/播放视频”。而 navigator.onLine === true 完全无法保证这些。常见错误是:检测到 online 就立刻重试请求,结果卡在 504 或超时。
更务实的做法是结合轻量探测:
- 对关键操作(如提交前)发起一个
fetch('/healthz')或fetch('/favicon.ico')(路径要同源、无缓存) - 设置短超时(
5s内无响应即视为不可用) - 把
navigator.onLine === false当作「强离线信号」,直接阻断操作并提示;true时再走探测流程
示例逻辑片段:
if (!navigator.onLine) {
showOfflineToast();
} else {
fetch('/healthz', { method: 'HEAD', cache: 'no-cache' })
.then(() => { /* 真实可用 */ })
.catch(() => { showOfflineToast(); });
}移动端 WebView 中 navigator.onLine 表现更不可靠
iOS WKWebView 和部分安卓 WebView 会缓存 navigator.onLine 状态长达数秒,甚至在飞行模式开关后仍返回旧值。Android 上还可能出现 onLine 为 true 但所有 fetch 都抛 TypeError: Network request failed 的情况。
应对方式:
- 不要依赖单次
navigator.onLine值,改用轮询(间隔3–5s)+ 探测请求组合判断 - 捕获全局
fetch失败,特别是TypeError和AbortError,它们比状态码更能反映底层断连 - 对用户可见的关键请求(如登录、支付),失败后手动触发一次探测,再决定是否弹出提示
真正的离线感知不是布尔值切换,而是持续观察 + 快速反馈。别让 navigator.onLine 成为你的唯一信标。

















