navigator.online仅反映浏览器网络栈状态而非真实连通性,常因路由器无外网、代理宕机、内网隔离或飞行模式残留而误判;需配合带超时的head请求(如/ping或/generate_204)并重试验证。

navigator.onLine 只能反映浏览器是否“认为自己在线”,不是真实网络连通性检测手段。
为什么 navigator.onLine 经常不准
这个属性本质是监听浏览器自身的网络栈状态切换(比如系统禁用Wi-Fi、拔掉网线),而不是发起真实请求验证能否访问互联网。它在以下场景完全失效:
- 设备连着Wi-Fi但路由器没上外网 →
navigator.onLine仍返回true - 使用代理且代理宕机 → 浏览器可能仍报告
true - 企业内网环境,能访问局域网但无法访问公网 → 无法区分
- 移动端切到飞行模式后又手动打开Wi-Fi(未自动重连)→ 偶尔卡在
false
如何配合 HTTP 请求做真实连通性判断
必须主动发一个轻量请求(如 /health 或已知稳定的 CDN 资源),靠响应结果判定。推荐用 fetch() 加超时控制:
async function isActuallyOnline() {
try {
const controller = new AbortController();
setTimeout(() => controller.abort(), 3000);
await fetch('/ping', { method: 'HEAD', signal: controller.signal });
return true;
} catch (e) {
return false;
}
}
注意点:
- 避免用
GET /,某些服务端会重定向或返回大页面,拖慢判断 - 优先选同域接口(避免跨域预检失败),若无则用
https://www.google.com/generate_204(返回 204 空响应) - 不要依赖单次请求:可尝试 1~2 次重试,但别轮询
- 移动端需注意节电策略可能中断后台 fetch,建议只在用户交互触发时检查
监听网络状态变化的正确姿势
window.addEventListener('online') 和 'offline' 是有用的,但仅用于响应系统级断连事件(如关Wi-Fi),不能替代真实探测:
- 它们触发时机早于
navigator.onLine值更新,适合提前清理缓存、暂停上传等操作 - 首次加载时
navigator.onLine的值不可靠,务必结合一次实际探测 - 不要在
online回调里直接重发失败请求——此时网络可能还没就绪,应加短延迟或轮询确认 - 部分 iOS WebView 会忽略这些事件,需降级为定时轮询
navigator.onLine+ 尝试请求
真正难的不是读取那个布尔值,而是理解浏览器对“在线”的定义和你业务需要的“可用”之间存在鸿沟。每次你准备依赖 navigator.onLine,都该问一句:用户此刻能成功提交表单吗?
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











