当前位置:首页 > 云服务器 > 正文

HTML5如何获取网络状态?判断手机网络类型

在 HTML5 开发中,获取网络状态主要依赖于 navigator.onLine 属性以及 online 和 offline 事件,需要明确的是,浏览器提供的原生 API 只能检测“设备是否连接到局域网或路由器”,而无法直接检测“该连接是否真正通向外网”,实际开发中通常需要结合原生 API 与自定义检测逻辑来实现更精准的网络状态监控。

基础 API:navigator.onLine

navigator.onLine 是一个只读布尔值属性,用于指示浏览器当前是否处于“在线”状态。

  • 返回值
    • true:表示设备已连接到网络(通常指已连接 Wi-Fi 或以太网)。
    • false:表示设备未连接到任何网络。

局限性

如果用户连接了 Wi-Fi,但路由器没有外网接入,navigator.onLine 仍然会返回 true,这被称为“假在线”状态。

HTML5如何获取网络状态?判断手机网络类型 第1张

事件监听:online 与 offline

为了实时响应用户的网络变化,可以监听 window 对象上的 online 和 offline 事件。

  • online 事件:当设备从离线变为在线时触发。
  • offline 事件:当设备从在线变为离线时触发。

进阶方案:自定义网络连通性检测

为了区分“连接了局域网”和“真正有外网访问能力”,我们需要编写一个自定义函数,通过发起一个轻量级的网络请求来验证连通性。

1 检测逻辑设计

  1. 首先检查 navigator.onLine。
  2. 如果为 false,直接判定为离线。
  3. 如果为 true,发起一个快速的 GET 请求(通常请求一个静态资源或一个轻量级的 API 端点)。
  4. 根据请求的成功或失败,结合超时机制,最终判定网络状态。

2 代码实现示例

以下是一个完整的 JavaScript 类,用于管理网络状态检测:

HTML5如何获取网络状态?判断手机网络类型 第2张

class NetworkMonitor { constructor() { this.isOnline = navigator.onLine; this.isReachable = false; // 是否真正连通外网 this.checkInterval = null; // 绑定事件 window.addEventListener('online', this.handleOnline.bind(this)); window.addEventListener('offline', this.handleOffline.bind(this)); // 初始化检测 this.checkConnectivity(); } // 发起连通性检测 async checkConnectivity() { if (!navigator.onLine) { this.updateStatus(false, false); return; } try { // 使用 fetch 请求一个可靠的静态资源,Google 的 1x1 像素图片 // 注意:跨域问题可能需要处理,或者使用同域下的轻量接口 const response = await fetch('https://www.google.com/favicon.ico', { method: 'HEAD', mode: 'no-cors', // 避免跨域报错,虽然无法读取响应内容,但能判断是否通 cache: 'no-store' // 确保每次都是新请求 }); // fetch 成功(即使 no-cors 模式下返回 opaque 响应),视为在线 this.updateStatus(true, true); } catch (error) { this.updateStatus(true, false); // 连接了局域网,但无外网 } } // 更新状态并触发回调 updateStatus(connected, reachable) { const previousStatus = this.isOnline; this.isOnline = connected; this.isReachable = reachable; // 如果状态发生变化,触发自定义事件 if (previousStatus !== connected || this.isReachable !== reachable) { window.dispatchEvent(new CustomEvent('network-status-change', { detail: { online: connected, reachable: reachable } })); } } handleOnline() { this.updateStatus(true, false); // 先标记为在线,稍后检测可达性 this.checkConnectivity(); } handleOffline() { this.updateStatus(false, false); } // 启动定期检测(可选,用于处理长时间连接但断网的情况) startPolling(intervalMs = 5000) { this.checkInterval = setInterval(() => {

HTML5如何获取网络状态?判断手机网络类型 第3张

this.checkConnectivity(); }, intervalMs); } stopPolling() { if (this.checkInterval) { clearInterval(this.checkInterval); } } } // 使用示例 const monitor = new NetworkMonitor(); // 监听状态变化 window.addEventListener('network-status-change', (e) => { console.log('网络状态变化:', e.detail); if (!e.detail.reachable) { alert('当前无外网连接,部分功能可能不可用'); } });

状态对比表

状态组合 navigator.onLine 自定义检测 (fetch) 用户实际体验 建议操作
完全离线 false N/A 无法访问任何网络资源 显示“无网络连接”提示,禁用需联网的功能
假在线 (无外网) true 失败/超时 能连 Wi-Fi 但打不开网页 显示“网络受限”提示,尝试加载本地缓存
完全在线 true 成功 正常访问互联网 正常业务逻辑,同步数据

注意事项与最佳实践

  1. 缓存策略:在检测网络时,务必设置 cache: 'no-store' 或添加随机参数(如 ?t=${Date.now()}),以防止浏览器缓存导致误判。
  2. 资源选择:用于检测的请求资源应尽可能小且稳定,Google 的

    favicon.ico 或 Cloudflare 的 1.1.1 是常见选择,但在生产环境中,建议请求自己服务器上的轻量级接口,以避免第三方服务不可用带来的误判。

  3. 移动端差异:在 iOS Safari 等某些移动端浏览器中,navigator.onLine 的行为可能略有不同,建议始终结合自定义检测使用。
  4. 性能优化:不要过于频繁地发起网络请求,建议仅在状态变化时检测,或使用合理的轮询间隔(如 5-10 秒)。
  5. 相关问题与解答

    Q1: 为什么 navigator.onLine 返回 true 但页面仍然无法加载?

    A: 这是因为 navigator.onLine 仅检测设备是否连接到本地网络接口(如 Wi-Fi 适配器或网线),它无法验证该网络是否具有互联网访问权限,当用户连接到公司内网,但内网防火墙阻止了外部访问,或者路由器本身未接通外网时,navigator.onLine 仍为 true,仅依赖此属性会导致“假在线”误判,必须结合实际的 HTTP 请求来验证连通性。

    Q2: 在 PWA(渐进式 Web 应用)中,如何更好地处理网络状态?

    A: PWA 的核心优势在于离线可用,除了上述的网络状态检测外,PWA 应充分利用 Service WorkerCache API

    1. 预缓存关键资源:在首次加载时,将核心 HTML、CSS、JS 及常用图片缓存到 Service Worker 中。
    2. 网络优先或缓存优先策略:在 Service Worker 的 fetch 事件中,根据网络状态决定是从网络获取最新数据,还是从缓存中读取旧数据。
    3. 后台同步:使用 Background Sync API,当网络恢复时,自动将离线期间用户产生的操作数据同步到服务器。

      结合 navigator.onLine 和 Service Worker,可以实现无缝的离线体验,而不仅仅是显示一个错误页面。

0