检测互联网连接是否离线?

373

我如何在JavaScript中检测互联网连接是否离线?


1
如果您可以或已经使用WebSockets - WebSockets具有必须调用的Close事件,如果用户失去与服务器的连接。 - Simon
2
这让我想起了90年代,当时你只需要声明图像事件,如image = new Image(); image.onload = onloadfunction; image.onerror = onerrorfunction; 然后设置image.src = "image.gif?" + Math.random(); 我认为这种方法今天仍然有效。 - PHP Guru
23个回答

252

几乎所有主流浏览器现在都支持 window.navigator.onLine 属性以及相应的 onlineoffline 窗口事件。运行以下代码片段进行测试:

console.log('Initially ' + (window.navigator.onLine ? 'on' : 'off') + 'line');

window.addEventListener('online', () => console.log('Became online'));
window.addEventListener('offline', () => console.log('Became offline'));

document.getElementById('statusCheck').addEventListener('click', () => console.log('window.navigator.onLine is ' + window.navigator.onLine));
<button id="statusCheck">Click to check the <tt>window.navigator.onLine</tt> property</button><br /><br />
Check the console below for results:

尝试将您的系统或浏览器设置为离线/在线模式,并检查日志或window.navigator.onLine属性以获取值更改。

然而,请注意来自Mozilla文档的以下引用:

在Chrome和Safari中,如果浏览器无法连接到本地区域网络(LAN)或路由器,则处于离线状态;所有其他条件返回true。因此,虽然当它返回false值时,您可以假定浏览器处于离线状态,但您不能假定true值必然意味着浏览器可以访问互联网。您可能会得到假阳性结果,例如在计算机运行具有始终“连接”的虚拟以太网适配器的虚拟化软件的情况下。因此,如果您真的想确定浏览器的在线状态,则应开发其他检查手段。

在Firefox和Internet Explorer中,将浏览器切换到脱机模式会发送false值。直到Firefox 41,所有其他条件都返回true值;自Firefox 41以来,在OS X和Windows上,该值将遵循实际的网络连接情况。

这意味着,如果window.navigator.onLinefalse,您保证没有互联网连接。

然而,如果它是true(或者你收到一个online事件),它只意味着系统连接到一些网络,最多。例如,它并不意味着您有Internet访问权。要检查这一点,您仍需要使用其他答案中描述的解决方案之一。

我最初打算将此作为对Grant Wagner的回答的更新发布,但觉得可能太大了,特别是考虑到2014年的更新已经不是他写的。


10
最近我有机会研究离线行为。离线事件非常好用,但ios Safari浏览器会出现问题。当你在手机上关闭互联网时,离线/在线事件会延迟最多2秒钟,这可能会影响可视化渲染,因为你无法预测未来。这只是我想提一下的事情,可能会帮助到别人。 - TeeJaay
@Sagar,我在 Firefox 和 Chrome 浏览器上进行了测试,如果我在连接到我的工作 VPN 时拔掉电缆,它们都可以快速检测到连接断开。然而,它们不会等待 VPN 重新连接才报告在线状态-如我在答案中指出的那样,online 只是表示您有某种连接,而不是表示您具有互联网访问权限。我抓住这个机会在我的回答中放了一段代码片段来测试它。 - Didier L
2
应该选择这个答案! - imike
1
@imike 这取决于提问者,但他已经超过10年没有活动了 :) 我希望能够超过被接受的答案,但不幸的是,这不会改变它们的顺序 - Didier L
对于未来的读者:自从我之前的评论以来,StackOverflow已经更改为仅按投票排序,忽略“已接受”的标志。现在你知道该怎么做了。 - Didier L
显示剩余3条评论

163

通过进行失败的XHR请求,您可以确定连接是否丢失。

标准方法是尝试重试请求几次。如果仍然无法成功,警告用户检查连接,并优雅地失败

附注:将整个应用程序置于“离线”状态可能会导致处理状态方面出现许多容易出错的工作.. 无线连接可能会存在不稳定性等问题。因此,最好只是优雅地失败,保留数据并提醒用户..让他们最终修复连接问题(如果有),并以相当宽容的方式继续使用您的应用程序。

附注:您可以检查可靠站点(例如Google)的连通性,但这可能不完全有用,因为与只尝试自己的请求相比,虽然Google可能可用,但您自己的应用程序可能不可用,您仍需处理自己的连接问题。尝试向google发送一个ping请求是确认互联网连接本身是否中断的好方法,因此,如果这些信息对您有用,则可能值得一试。

注意事项: 发送Ping可以通过与进行任何双向Ajax请求相同的方式实现,但是在这种情况下向Google发送Ping会遇到一些挑战。首先,我们将遇到通常在进行Ajax通信时遇到的跨域问题。其中一个选项是设置服务器代理,在其中实际上ping Google(或任何网站),并将Ping的结果返回给应用程序。这是一个进退两难,因为如果互联网连接实际上是问题所在,我们将无法访问服务器,而且如果连接问题仅存在于我们自己的域中,我们也无法区分差异。其他跨域技术可以尝试,例如在页面中嵌入指向Google.com的iframe,然后轮询iframe的成功/失败(检查内容等)。嵌入图像可能无法告诉我们任何东西,因为我们需要从通信机制中获得有用的响应,以便就当前状况得出良好结论。因此,确定整个互联网连接状态可能比得上它带来的麻烦还要多。您必须权衡这些选项以适用于您特定的应用程序。


41
2012年,您可以检查变量navigator.onLine ;) - João Pinto Jerónimo
19
同样的原因,navigator.online/offline 也是不可靠的。请参考 https://dev59.com/uHA75IYBdhLWcg3wqKx0。 - Efran Cobisi
20
您可以查看Offline.js,这是一个专门为此目的构建的开源库。 - Adam
3
除了可靠性问题(所有解决方案都存在此问题),navigator.onLine 明显是目前最好的解决方案,因为它已经支持跨浏览器了(参见 http://caniuse.com/#feat=online-status)。 - Stijn de Witt
“一种选择是设置一个服务器端代理,我们实际上会ping谷歌(或其他网站),并将ping的结果返回给应用程序。” 不应该将其作为可能的解决方案来阐述。即使我连接到我的服务器,我也想检查我是否可以访问谷歌,而不是我的服务器。 - Marinos An

60

IE 8将支持 window.navigator.onLine 属性。

但是当然,这不能解决其他浏览器或操作系统的问题。我预测其他浏览器供应商会考虑提供该属性,鉴于在Ajax应用程序中了解在线/离线状态的重要性。

在此之前,可以使用XHR或Image()<img>请求来提供接近所需功能的东西。

更新(2014/11/16)

主流浏览器现在都支持这个属性,但你的结果可能会有所不同。

引用自Mozilla文档:

在Chrome和Safari中,如果浏览器无法连接到本地区域网络(LAN)或路由器,则处于离线状态;所有其他情况均返回true。因此,当它返回false值时,您可以假定浏览器处于离线状态,但您不能假定真值必然意味着浏览器可以访问互联网。您可能会得到错误的结果,例如在计算机运行具有虚拟以太网适配器的虚拟化软件的情况下。因此,如果您确实想确定浏览器的在线状态,则应开发其他检查方法。

在Firefox和Internet Explorer中,将浏览器切换到离线模式会发送false值。所有其他情况均返回true值。


6
navigator.onLine 是 HTML5 的一部分 -- 其他浏览器已经有提供它的开发版本 -- 它今天在 Firefox 3 中已经可用。 - olliej
但不幸的是,它在早期版本的IE中不可用,而我们经常需要支持这些版本。 - keparo
26
navigator.onLine显示的是浏览器的状态,而非实际连接状态。因此,你可能已将浏览器设置为在线,但实际上连接失败了。只有当浏览器设置为离线浏览时,navigator.onLine才会为false。 - user327117
7
如果我在Nexus7上关闭WI-FI,页面仍然显示navigator.onLine为TRUE。很糟糕... - walv

45
if (navigator.onLine) {
  alert('online');
} else {
  alert('offline');
}

查看{{link1:onLine的基本用法}}


21
如果在浏览器上,它将始终返回TRUE。 - Slavcho
4
起初,我试图禁用仅限局域网(LAN)的网络,但它总是返回TRUE。因此,当我禁用了所有网络(LAN2,Virtual Box等)时,它返回了FALSE。 - Slavcho
4
这个答案复制了3年前的几个已有的答案。 - JasonMArcher
3
它不检查互联网连接性,它只检查本地网络连接性。 - Suganth G
1
在所有浏览器中它始终返回true。 - mitesh7172
显示剩余6条评论

40

有几种方法可以做到这一点:

  • AJAX请求到您自己的网站。如果该请求失败,很可能是连接出了问题。JQuery文档中有一个关于处理失败的AJAX请求的部分。在执行此操作时,请注意同源策略,它可能会阻止您访问域外的站点。
  • 您可以在img中放置onerror,例如:<img src="http://www.example.com/singlepixel.gif" onerror="alert('Connection dead');" />

如果源图像移动/重命名,则此方法也可能失败,并且通常比ajax选项差。

因此,有几种不同的方法可以尝试检测到这一点,但没有完美的方法,在无法跳出浏览器沙箱并直接访问用户的网络连接状态的情况下,它们似乎是最佳选择。


17

正如olliej所说,使用navigator.onLine浏览器属性比发送网络请求更可取,并且根据developer.mozilla.org/En/Online_and_offline_events的说明,即使是旧版本的Firefox和IE也支持它。

最近,WHATWG已经指定了添加onlineoffline事件,以便在需要对navigator.onLine更改做出反应时使用。

请注意Daniel Silveira发布的链接,该链接指出仅依赖这些信号/属性与服务器同步并不总是一个好主意。


更新:截至2015年,它似乎在大多数浏览器中都可以使用,请参见[caniuse图表](http://caniuse.com/#feat=online-status)和[文章](https://davidwalsh.name/detecting-online). - Olga

12
window.navigator.onLine

这就是你要找的内容,但还需要补充一些东西。首先,如果你想一直检查应用程序中的某些东西(比如看看用户是否突然离线,在这种情况下大部分时间都是正确的),那么你需要添加事件监听器来检测任何更改。为了检查用户是否离线,你可以执行以下操作:

window.addEventListener("offline", 
  ()=> console.log("No Internet")
);

用于检查是否在线:

window.addEventListener("online", 
  ()=> console.log("Connected Internet")
);

7
你必须小心处理onLine。浏览器对于在线状态的定义有很大不同。请参考 https://developer.mozilla.org/en-US/docs/Web/API/NavigatorOnLine/onLine。 - Andreas Baumgart
2
同时,这只有在您进行请求时才是可靠的。只需关闭您的WiFi或拔掉以太网线并检查此属性。仍然为真。 - Douglas Gaskell

11
你可以使用$.ajax()error回调函数,如果请求失败就会触发。如果textStatus等于字符串"timeout",那么很可能是连接中断了。
function (XMLHttpRequest, textStatus, errorThrown) {
  // typically only one of textStatus or errorThrown 
  // will have info
  this; // the options for this ajax request
}

根据文档:

Error: 如果请求失败,将调用一个函数。函数传入三个参数: XMLHttpRequest对象, 描述发生的错误类型的字符串和可选的异常对象(如果有)。第二个参数可能的值(除了null)包括:"timeout", "error", "notmodified" 和 "parsererror"。这是一个Ajax事件。

例如:

 $.ajax({
   type: "GET",
   url: "keepalive.php",
   success: function(msg){
     alert("Connection active!")
   },
   error: function(XMLHttpRequest, textStatus, errorThrown) {
       if(textStatus == 'timeout') {
           alert('Connection seems dead!');
       }
   }
 });

10

HTML5应用缓存API指定了navigator.onLine。该属性目前在IE8测试版、WebKit(例如Safari)每夜构建版本中提供,并且已经在Firefox 3中得到支持。


4
正如在另一个答案中所讨论的那样,这实际上并不像预期的那样工作。即使没有互联网,navigator.onLine 仍将返回 true - TheCarver

9

通过向您的域发出ajax调用是检测您是否离线的最简单方法。

$.ajax({
      type: "HEAD",
      url: document.location.pathname + "?param=" + new Date(),
      error: function() { return false; },
      success: function() { return true; }
   });

这只是为了让您理解概念,需要改进。

例如,错误=404仍应该意味着您在线。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接