Back

如何在 JavaScript 中检测在线和离线状态

如何在 JavaScript 中检测在线和离线状态

你的应用看起来运行良好——直到用户在会话中途失去连接,所有功能都无法使用。在 JavaScript 中检测在线和离线状态可以让你优雅地响应:显示警告横幅、暂停网络请求,或在连接恢复时自动重试。以下是可靠实现的方法。

核心要点

  • 使用 navigator.onLine 在页面加载时检查连接状态,使用 online/offline 窗口事件实时响应状态变化。
  • navigator.onLine 返回 true 并不保证真正的互联网访问——它仅确认设备已连接到某个网络。
  • 在恢复关键操作之前,通过向自己的后端发送轻量级 fetch 请求来验证真实连接性。
  • 结合这三种方法实现健壮的、生产就绪的离线处理。

快速解答:navigator.onLine 和窗口事件

浏览器为 JavaScript 在线/离线检测提供了两个工具:

  • navigator.onLine — 一个可以随时读取的布尔属性
  • onlineoffline 窗口事件 — 在连接状态改变时触发

它们共同覆盖了你关心的两种场景:在页面加载时检查状态以及在状态改变时做出响应。

在页面加载时读取 navigator.onLine

if (navigator.onLine) {
  console.log('Browser reports online')
} else {
  console.log('Browser reports offline')
}

这对于在页面首次加载时设置初始 UI 状态很有用——例如,如果用户已经离线,则禁用”同步”按钮。

在 JavaScript 中监听在线和离线事件

使用定时器轮询 navigator.onLine 是浪费资源的。相反,应使用 window 上的 onlineoffline 事件:

window.addEventListener('online', () => {
  console.log('Connection restored')
  // Re-enable UI, retry pending requests
})

window.addEventListener('offline', () => {
  console.log('Connection lost')
  // Show offline banner, disable network actions
})

这些事件在浏览器检测到网络状态变化时自动触发,因此你的应用可以立即响应,无需任何轮询开销。

实用示例:显示离线横幅

以下是结合两种方法的最小化、生产就绪模式:

const banner = document.getElementById('offline-banner')

function updateOnlineStatus() {
  banner.hidden = navigator.onLine
}

// Set initial state
updateOnlineStatus()

// React to changes
window.addEventListener('online', updateOnlineStatus)
window.addEventListener('offline', updateOnlineStatus)
<div id="offline-banner" hidden>
  You're offline. Some features may be unavailable.
</div>

这种模式简洁、事件驱动,并且避免了内存泄漏,因为监听器只附加一次并重用相同的处理函数。

这是大多数教程解释不足的部分。navigator.onLine 不能确认实际的互联网访问。

  • false 是可靠的——浏览器确实处于离线状态。
  • true 仅表示设备已连接到某个网络(路由器、VPN 适配器、局域网)。用户可能处于强制门户后面,或者你的后端可能无法访问。

**不要将 navigator.onLine 返回 true 视为连接性的证明。**将其用作用户可能在线的提示,而不是确认他们已连接。

通过网络请求验证真实连接性

navigator.onLine 返回 true 但关键操作失败时,通过向自己的后端发送轻量级请求来确认可达性:

async function isReachable() {
  try {
    const response = await fetch('/health-check', {
      method: 'HEAD',
      cache: 'no-store',
    })
    return response.ok
  } catch {
    return false
  }
}

使用你自己的端点——而不是第三方 URL——以避免 CORS 问题。对小型、快速路由发送 HEAD 请求可将带宽影响降至最低。

可选:网络信息 API

对于连接质量提示(不仅仅是在线/离线),navigator.connection 暴露了诸如 effectiveType('4g''3g''slow-2g')和 downlink 等属性。浏览器支持仅限于基于 Chromium 的浏览器——仅将其视为渐进增强。

在开发者工具中测试离线行为

打开 Chrome 开发者工具 → Network 标签 → 将限速下拉菜单设置为 Offline。这会触发 offline 事件并将 navigator.onLine 设置为 false,让你无需断开计算机连接即可测试 UI。

结论

在 JavaScript 中检测在线状态归结为三件事:在加载时读取 navigator.onLine,监听 online/offline 事件以响应变化,并在恢复关键操作之前通过 fetch 请求验证真实连接性。这种组合可以干净高效地处理绝大多数真实世界的连接场景。

常见问题

不可以。navigator.onLine 返回 true 仅表示设备已连接到某个网络,例如路由器或 VPN 适配器。它不保证实际的互联网访问。用户可能处于强制门户后面,或者你的服务器可能已关闭。对于关键操作,始终通过真实的网络请求进行验证。

是的。online 和 offline 窗口事件以及 navigator.onLine 属性在所有现代浏览器中都受支持,包括 Chrome、Firefox、Safari 和 Edge。它们是 HTML 规范的一部分,多年来一直得到广泛支持。

向自己服务器上的健康检查端点发送轻量级 fetch 请求,例如 HEAD 请求。使用 cache no-store 绕过浏览器缓存。如果请求成功并返回 ok 状态,则用户具有真正的连接性。避免 ping 第三方 URL 以防止 CORS 问题。

网络信息 API 提供了有用的提示,如有效连接类型和下行速度,但浏览器支持仅限于基于 Chromium 的浏览器。Safari 和 Firefox 不支持它。将其视为渐进增强,并始终为不支持的浏览器提供后备行为。

Complete picture for complete understanding

Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.

Check our GitHub repo and join the thousands of developers in our community.

OpenReplay