检测到Internet连接是否脱机?

Dan*_*ira 220 javascript ajax offline connectivity internet-connection

如何在JavaScript中检测Internet连接是否脱机?

kep*_*aro 131

您可以通过发出失败的XHR请求来确定连接丢失.

标准方法是重试请求几次.如果未通过,则提醒用户检查连接,并正常失败.

旁注:将整个应用程序置于"离线"状态可能会导致很多容易出错的处理状态工作..无线连接可能会来来去去等等.所以你最好的选择可能就是优雅地失败,保留数据,并警告用户..允许他们最终解决连接问题,如果有的话,并继续使用你的应用程序与相当多的宽恕.

旁注:您可以检查一个像google这样可靠的网站进行连接,但这可能并不完全有用,因为只是尝试发出自己的请求,因为虽然谷歌可能可用,但您自己的应用可能不是,而您仍然会必须处理自己的连接问题.尝试向谷歌发送ping将是确认互联网连接本身已关闭的好方法,所以如果这些信息对您有用,那么它可能是值得的.

旁注:发送Ping可以通过与制作任何类型的双向ajax请求相同的方式实现,但是在这种情况下向谷歌发送ping会带来一些挑战.首先,我们遇到了与进行Ajax通信时通常遇到的相同的跨域问题.一种选择是设置服务器端代理,其中我们实际上ping谷歌(或任何网站),并将ping的结果返回给应用程序.这是一个捕获22因为如果互联网连接实际上是问题,我们将无法访问服务器,如果连接问题仅在我们自己的域上,我们将无法区分.可以尝试其他跨域技术,例如,在您的页面中嵌入指向google.com的iframe,然后轮询iframe的成功/失败(检查内容等).嵌入图像可能并不能真正告诉我们什么,因为我们需要来自通信机制的有用响应,以便对正在发生的事情得出一个好的结论.因此,再次确定整个互联网连接的状态可能比它的价值更麻烦.您必须为特定应用加重这些选项.

  • 重复的"Sidenote"听起来像Dwight Schrute说"问题......":-) (80认同)
  • 现在在2012年,您可以检查变量navigator.onLine;) (32认同)
  • 为什么"catch-22"以粗体显示? (18认同)
  • 您可能需要查看[Offline.js](https://github.com/HubSpot/offline),这是一个为此目的而构建的开源库. (17认同)
  • navigator.online/offline也是不可靠的,出于同样的原因.请参见http://stackoverflow.com/questions/3181080/how-to-detect-online-offline-event-cross-browser (13认同)
  • 撇开可靠性问题不谈(所有解决方案都存在这个问题),`navigator.onLine` 绝对是最好的,因为[它是跨浏览器](http://caniuse.com/#feat=online-status)。 (2认同)

Gra*_*ner 49

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

但当然这对其他浏览器或操作系统没有帮助.我预测,鉴于了解Ajax应用程序中的在线/离线状态的重要性,其他浏览器供应商也将决定提供该属性.

在此之前,无论是XHR或Image()<img>请求可以提供一些接近你想要的功能.

更新(2014/11/16)

主流浏览器现在支持此属性,但您的结果会有所不同.

来自Mozilla文档的引用:

在Chrome和Safari中,如果浏览器无法连接到局域网(LAN)或路由器,则它处于脱机状态; 所有其他条件都返回true.因此,虽然您可以假设浏览器在返回false值时处于脱机状态,但您不能认为真值必然意味着浏览器可以访问Internet.您可能会收到误报,例如计算机运行的虚拟化软件具有始终"连接"的虚拟以太网适配器.因此,如果您确实想确定浏览器的在线状态,则应开发其他检查方法.

在Firefox和Internet Explorer中,将浏览器切换到脱机模式会发送一个false值.所有其他条件都返回一个true值.

  • navigator.onLine显示浏览器的状态,而不是实际连接.所以你可以将你的浏览器设置为onLine,但实际上它会失败,因为连接已关闭.如果浏览器设置为脱机浏览,navigator.onLine将仅为false. (20认同)
  • navigator.onLine是HTML5的一部分 - 其他浏览器已经有提供它的开发版本 - 它现在已经在Firefox 3中提供. (5认同)
  • 如果我在Nexus7上关闭WI-FI,页面仍然说navigator.onLine为TRUE.坏... (4认同)

Con*_*oyP 35

有很多方法可以做到这一点:

  • AJAX请求到您自己的网站.如果该请求失败,则很可能是连接出错.在JQuery的文件有一个部分处理失败的AJAX请求.执行此操作时请注意同源策略,这可能会阻止您访问域外的站点.
  • 你可以放onerror一个img,像

    <img src='http://www.example.com/singlepixel.gif' 
          onerror='alert("Connection dead");' />
    
    Run Code Online (Sandbox Code Playgroud)

    如果移动/重命名源图像,此方法也可能失败,并且通常是ajax选项的劣质选择.

所以有几种不同的方法可以尝试和检测这一点,没有一个完美,但由于缺乏跳出浏览器沙箱并直接访问用户的网络连接状态的能力,它们似乎是最好的选择.

  • 主要浏览器不一致支持onerror. (5认同)

Edm*_*mhs 32

 if(navigator.onLine){
  alert('online');
 } else {
  alert('offline');
 }
Run Code Online (Sandbox Code Playgroud)

  • 如果在浏览器上,它返回TRUE. (8认同)
  • 这个答案重复了3年前的几个现有答案. (3认同)
  • 首先,我试图禁用ONLY LAN,但它始终返回TRUE.因此,当我禁用所有网络(LAN2,Virtual Box等)时,它返回FALSE. (2认同)
  • 它不检查互联网连接,它只检查LAN连接 (2认同)

Did*_*r L 22

几乎所有的主流浏览器都支持的window.navigator.onLine特性,以及相应onlineoffline窗口事件:

window.addEventListener('online', () => console.log('came online'));
window.addEventListener('offline', () => console.log('came offline'));
Run Code Online (Sandbox Code Playgroud)

尝试在离线/在线模式下设置系统或浏览器,并检查控制台或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(或者你得到一个offline事件),你可以保证没有互联网连接.

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

我最初打算将此作为Grant Wagner答案的更新发布,但这似乎太过于编辑,特别是考虑到2014年更新已经不是他的了.

  • 最佳答案。谢谢。 (4认同)
  • 我最近有机会研究一下线下行为。这些事件很好用,但 ios safari 会产生问题。当您关闭手机上的互联网时,离线/在线事件将延迟最多 2 秒,这可能会因视觉渲染原因而出现问题,因为您无法预测未来。这只是我想提及的事情,可能会对某人有所帮助。 (4认同)
  • 应该选答案! (2认同)

oll*_*iej 11

HTML5应用程序缓存API指定了navigator.onLine,它目前可在IE8测试版,WebKit(例如Safari)中使用,并且已在Firefox 3中受支持

  • 正如另一个答案所讨论的,这实际上并没有按预期工作。即使您没有互联网,“navigator.onLine”仍将返回“true”。 (4认同)

Ali*_*eza 11

window.navigator.onLine
Run Code Online (Sandbox Code Playgroud)

是您要查找的内容,但这里几乎没有要添加的内容,首先,如果您想继续检查应用程序中的某些内容(例如查看用户是否突然离线,在大多数情况下是正确的,那么您还需要监听更改),为此您将事件侦听器添加到窗口以检测任何更改,检查用户是否离线,您可以执行以下操作:

window.addEventListener("offline", 
  ()=> console.log("No Internet")
);
Run Code Online (Sandbox Code Playgroud)

并检查是否在线:

window.addEventListener("online", 
  ()=> console.log("Connected Internet")
);
Run Code Online (Sandbox Code Playgroud)

  • 你必须小心“onLine”。浏览器对在线状态的定义非常不同。请查看 https://developer.mozilla.org/en-US/docs/Web/API/NavigatorOnLine/onLine。 (5认同)
  • 此外,只有当您提出请求时,这才是可靠的。只需关闭您的 wifi 或拔掉以太网并检查此属性即可。尚真。 (2认同)

Gid*_*aya 10

我知道这个问题已经得到解答,但我想添加我的 10 美分来解释什么是更好的,什么是不好的。

Window.navigator.onLine

我注意到一些答案谈到了这个选项,但他们从未提到任何有关警告的内容。

此选项涉及使用“ window.navigator.onLine ”,它是大多数现代浏览器上可用的浏览器导航器界面下的一个属性。这确实不是检查互联网可用性的可行选择,因为首先it is browser centric和其次most browsers implement this property differently

在 Firefox 中:该属性返回一个布尔值,表示true在线和false离线,但这里需要注意的是“ the value is only updated when the user follows links or when a script requests a remote page.”因此,如果用户离线并且您从 js 函数或脚本查询该属性,该属性将始终返回,true直到用户跟随一个链接。

在 Chrome 和 Safari 中:如果浏览器无法连接到局域网 (LAN) 或路由器,则表示浏览器处于离线状态;所有其他条件返回 true。因此,虽然您可以假设浏览器在返回 false 值时处于离线状态,但您不能假设 true 值一定意味着浏览器可以访问互联网。您可能会收到误报,例如计算机运行的虚拟化软件具有始终“连接”的虚拟以太网适配器。

上面的陈述只是想让你知道单靠浏览器是无法判断的。所以基本上这个选项是不可靠的。

向自己的服务器资源发送请求

这涉及到向您自己的服务器资源发出 HTTP 请求,如果可以访问,则假定互联网可用,否则用户处于离线状态。此选项有一些注意事项。
  1. 没有服务器的可用性是 100% 可靠的,因此,如果由于某种原因无法访问您的服务器,则会错误地认为用户在连接到互联网时处于离线状态。
  2. 对同一资源的多个请求可能会返回缓存的响应,从而使 http 响应结果不可靠。

如果您同意您的服务器始终在线,那么您可以选择此选项。

这是一个获取自己的资源的简单片段:

// This fetches your website's favicon, so replace path with favicon url
// Notice the appended date param which helps prevent browser caching.
fetch('/favicon.ico?d='+Date.now())
  .then(response => {
    if (!response.ok)
      throw new Error('Network response was not ok');

   // At this point we can safely assume the user has connection to the internet
        console.log("Internet connection available"); 
  })
  .catch(error => {
  // The resource could not be reached
        console.log("No Internet connection", error);
  });
Run Code Online (Sandbox Code Playgroud)

向第三方服务器资源发送请求

我们都知道 CORS 是一个东西。

此选项涉及向外部服务器资源发出 HTTP 请求,如果可以访问,则假定互联网可用,否则用户处于脱机状态。对此的主要警告是跨源资源共享,这是一个限制。大多数信誉良好的网站都会阻止 CORS 请求,但对于某些网站,您可以随心所欲。

下面是一个获取外部资源的简单代码片段,与上面相同,但具有外部资源 url:

// Firstly you trigger a resource available from a reputable site
// For demo purpose you can use the favicon from MSN website
// Also notice the appended date param which helps skip browser caching.
fetch('https://static-global-s-msn-com.akamaized.net/hp-neu/sc/2b/a5ea21.ico?d='+Date.now())
  .then(response => {
  // Check if the response is successful
    if (!response.ok)
      throw new Error('Network response was not ok');

// At this point we can safely say the user has connection to the internet
        console.log("Internet available"); 
  })
  .catch(error => {
  // The resource could not be reached
        console.log("No Internet connection", error);
  });
Run Code Online (Sandbox Code Playgroud)

因此,最后,对于我的个人项目,我选择了第二个选项,其中涉及请求自己的服务器资源,因为基本上有很多因素可以判断用户设备上是否有“互联网连接”,而不仅仅是来自您的网站容器,也不仅仅是来自有限的服务器资源。浏览器 API。

请记住,您的用户也可能处于某些网站或资源被阻止、禁止和无法访问的环境中,这反过来会影响连接检查的逻辑。最好的选择是:

  • 尝试访问您自己的服务器上的资源,因为这是您的用户环境(通常我使用网站的图标,因为响应非常轻并且不经常更新)。
  • 如果没有与资源的连接,当您需要通知用户时,只需说“连接错误”或“连接丢失”,而不是假设广泛的“无互联网连接”,这取决于许多因素。


kar*_*m79 9

您可以使用$ .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
}
Run Code Online (Sandbox Code Playgroud)

来自doc:

错误:请求失败时要调用的函数.该函数传递三个参数: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!');
       }
   }
 });
Run Code Online (Sandbox Code Playgroud)


小智 9

正如olliej所说,使用navigator.onLine浏览器属性比发送网络请求更可取,因此使用developer.mozilla.org/En/Online_and_offline_events,旧版本的Firefox和IE甚至支持它.

最近,WHATWG已指定添加onlineoffline事件,以防您需要对navigator.onLine更改做出反应.

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


小智 6

我必须为经常在学校工作的客户制作一个Web应用程序(基于ajax),这些学校的互联网连接通常很差,我使用此简单功能来检测是否存在连接,效果很好!

我使用CodeIgniter和Jquery:

function checkOnline() {
    setTimeout("doOnlineCheck()", 20000);
}

function doOnlineCheck() {
    //if the server can be reached it returns 1, other wise it times out
    var submitURL = $("#base_path").val() + "index.php/menu/online";

    $.ajax({
        url : submitURL,
        type : "post",
        dataType : "msg",
        timeout : 5000,
        success : function(msg) {
            if(msg==1) {
                $("#online").addClass("online");
                $("#online").removeClass("offline");
            } else {
                $("#online").addClass("offline");
                $("#online").removeClass("online");
            }
            checkOnline();
        },
        error : function() {
            $("#online").addClass("offline");
            $("#online").removeClass("online");
            checkOnline();
        }
    });
}
Run Code Online (Sandbox Code Playgroud)


har*_*shr 6

对您的域进行ajax调用是检测您是否离线的最简单方法

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

这只是给您的概念,应该加以改进。

例如error = 404应该仍然表示您在线


Pra*_*amy 5

我认为这是一种非常简单的方法。

var x = confirm("Are you sure you want to submit?");
if (x) {
  if (navigator.onLine == true) {
    return true;
  }
  alert('Internet connection is lost');
  return false;
}
return false;
Run Code Online (Sandbox Code Playgroud)

  • onLine 并不意味着有互联网连接。根据 https://developer.mozilla.org/en-US/docs/Web/API/NavigatorOnLine/onLine ```如果浏览器无法连接到局域网 (LAN) 或路由器,则离线; 所有其他条件返回 true``` (2认同)