必须先校验"connection" in navigator且navigator.connection !== null,再验证type为有效字符串、downlink > 0;saveData才是省流关键依据,需三重判空后读取,不可依赖onLine或type判断真实网络质量。

navigator.connection 不是“拿来即用”的 API,直接读取 type 或 downlink 会踩空、报错、误判——必须做存在性校验 + 属性有效性验证 + 降级兜底。
怎么安全地读取 navigator.connection 的值
很多浏览器(比如 Safari、旧版 Chrome、部分 Android WebView)会返回一个“空壳”对象:它存在,但所有属性都是 undefined 或默认值(如 downlink: 0)。直接访问会得到 NaN、0 或抛错。
- 先检查是否存在且非空:
"connection" in navigator && navigator.connection !== null - 再验证关键字段是否“可读”:
typeof navigator.connection.type === "string" && navigator.connection.type !== "unknown" - 对
downlink做容错:Number(navigator.connection.downlink) > 0,避免0或NaN被当作有效带宽 - 别碰
rtt:Chrome移动版常返回0或固定值(如50),无实际参考意义
为什么不能只靠 navigator.onLine 判断真实连通性
navigator.onLine 只读系统网络接口状态(Wi-Fi 是否启用、以太网是否插线),完全不验证 DNS、代理、路由器或后端服务是否可达。拔网线能触发变化,但重启路由器、DNS 故障、防火墙拦截——它一概不知。
- 首次检查应在
online或offline事件触发后才采信,不要依赖初始值 - 它无法区分「有网络但服务器不可达」和「完全断网」,仅适合做粗粒度提示(如显示“离线中…”)
- 某些 PWA 场景下,Service Worker 可能拦截请求但
navigator.onLine仍为true,需结合fetch超时判断 - 验证真实连通性推荐用
fetch('/favicon.ico', { method: 'HEAD' })加AbortController控制超时(3s 内)
saveData 比 type === "cellular" 更值得信任的原因
省流策略不该只看是不是蜂窝网络。iOS 低数据模式、Android 数据节省程序开启时,navigator.connection.saveData 才是系统级的真实意图信号。
立即学习“前端免费学习笔记(深入)”;
- 必须先检查
"saveData" in navigator.connection,不能直接访问navigator.connection.saveData - 值为
true时,应立即停用高清图、视频自动播放、非关键 JS bundle 预加载等行为 - 该值不会触发
change事件,无法监听;桌面浏览器基本不支持;部分安卓 WebView 也不同步系统设置 - fallback 方案:当
saveData不可用时,用Number(navigator.connection.downlink) 粗略模拟
effectiveType 和 type 的实际含义与常见误判
type 返回的是底层网络接口类型,不是用户感知的“信号强弱”或“网速快慢”。例如:"cellular" 可能是满格 5G,也可能是边缘地带的 2G;"wifi" 可能连着千兆光猫,也可能只是被限速的机场热点。
-
"none"表示设备已断网(此时navigator.onLine通常为false),但反过来navigator.onLine === true不代表type一定有效 -
"other"多见于定制 Android 系统或企业 MDM 环境,无法进一步区分,建议统一视为“未知网络” -
effectiveType(如"4g"、"slow-2g")比type更贴近体验,但它仍是估算值,且兼容性更差(Safari 完全不支持) - 不要把
type === "cellular"当作“该省流量”的唯一依据:iOS 低数据模式下,type仍是"cellular",但saveData才是关键开关
真正可靠的网络判断永远是分层的:先用 navigator.onLine 快速过滤明显离线场景,再用 navigator.connection 做粗粒度分类,最后用轻量 fetch 验证目标服务可达性——三者缺一不可,且每一层都要有 fallback。

















