检测到Internet连接是否脱机?

时间:2008-10-09 22:23:50

标签: javascript ajax offline connectivity internet-connection

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

22 个答案:

答案 0 :(得分:123)

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

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

旁注:将整个应用程序置于“离线”状态可能会导致很多容易出错的处理状态工作..无线连接可能会来来去去等等所以你最好下注可能只是优雅地失败,保留数据,并提醒用户..允许他们最终修复连接问题(如果有的话),并继续使用您的应用程序并获得相当大的宽恕。

旁注:您可以查看google之类的可靠网站以获取连接,但这可能并不完全有用,因为只是尝试发出自己的请求,因为虽然Google可用,但您自己的应用可能不是,你仍然需要处理自己的连接问题。尝试向谷歌发送ping将是确认互联网连接本身已关闭的好方法,所以如果这些信息对您有用,那么它可能是值得的。

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

答案 1 :(得分:45)

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

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

在此之前,XHR或Image()<img>请求都可以提供您想要的功能。

更新(2014/11/16)

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

引自Mozilla Documentation

  

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

     

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

答案 2 :(得分:33)

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

  • AJAX请求到您自己的网站。如果该请求失败,则很可能是连接出错。 JQuery文档中有handling failed AJAX requests部分。这样做时要小心Same Origin Policy,这可能会阻止您访问域外的网站。
  • 您可以在onerror中添加img,例如

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

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

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

答案 3 :(得分:29)

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

答案 4 :(得分:13)

Almost all major browsers现在支持window.navigator.onLine属性,以及相应的onlineoffline窗口事件:

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

尝试将系统或浏览器设置为离线/在线模式,然后检查控制台或window.navigator.onLine属性的值更改。您也可以在this website上对其进行测试。

但是请注意Mozilla Documentation中的这句话:

  

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

     

在Firefox和Internet Explorer中,将浏览器切换为脱机模式将发送一个false值。在Firefox 41之前,所有其他条件都返回true值;从Firefox 41开始,在OS X和Windows上,该值将遵循实际的网络连接。

(强调是我自己的)

这意味着,如果window.navigator.onLinefalse(或者您收到offline事件),则可以保证没有Internet连接。

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

我最初打算将此内容发布为对Grant Wagner's answer的更新,但似乎太过编辑,尤其是考虑到2014年的更新已经not from him < / p>

答案 5 :(得分:11)

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

答案 6 :(得分:9)

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

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

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

答案 7 :(得分:8)

您可以使用$.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
}

来自doc

  

错误:请求时要调用的函数   失败。该功能通过三次   arguments:XMLHttpRequest对象,   描述错误类型的字符串   发生了并且是可选的   异常对象,如果发生了一个。   第二个可能的值   参数(除了null)是“超时”,   “错误”,“未修改”和   “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!');
       }
   }
 });

答案 8 :(得分:4)

我必须为一个与学校一起工作的客户制作一个网络应用程序(基于ajax),这些学校经常有一个糟糕的互联网连接,我使用这个简单的功能来检测是否有连接,效果很好! / p>

我使用CodeIgniter和Jquery:

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

function doOnlineCheck(){
    var submitURL = $("#base_path").val() + "index.php/menu/online";//if the server can be reached it returns 1, other wise it times out
    $.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();
        }
    });
}

答案 9 :(得分:4)

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

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

这只是为了给你概念,它应该改进,检查返回http状态代码等

答案 10 :(得分:4)

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

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;

答案 11 :(得分:2)

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

Window.navigator.onLine

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

此选项涉及使用“ window.navigator.onLine”,这是大多数现代浏览器上可用的Browser Navigator Interface下的属性。这实际上不是检查互联网可用性的可行选择,因为首先是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。因此,尽管您可以假设浏览器是 脱机时,如果它返回一个假值,则不能假定为真 价值必然意味着浏览器可以访问互联网。您 可能会得到误报,例如在计算机 正在运行具有虚拟以太网的虚拟化软件 始终处于“连接”状态的适配器。

以上陈述只是想让您知道,仅浏览器无法分辨。因此,基本上,此选项不可靠。

发送请求以拥有服务器资源

这涉及向您自己的服务器资源发出HTTP请求,如果可以访问,则假定Internet可用,否则用户处于脱机状态。此选项有一些警告。
  1. 没有服务器可用性是100%依赖的,因此,如果由于某种原因无法访问服务器,则会错误地假定用户处于脱机状态,而他们已连接到Internet。
  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);
  });

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

众所周知,CORS是一回事。

此选项涉及到对外部服务器资源的HTTP请求,如果可以访问,则假定Internet可用,否则用户处于脱机状态。主要的警告是Cross-origin resource sharing,它是一个限制。大多数信誉良好的网站都会阻止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);
  });

因此,最后,对于我的个人项目,我选择了第二个选项,该选项涉及请求自己的服务器资源,因为基本上有很多因素可以判断用户设备上是否存在“ Internet连接”,而不仅仅是从您的网站容器中或者通过有限的浏览器api。

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

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

答案 12 :(得分:1)

我一直在寻找一个客户端解决方案,以检测互联网是否关闭或我的服务器是否已关闭。我发现的其他解决方案似乎总是依赖于第三方脚本文件或图像,这对我来说似乎不会经得起时间的考验。外部托管脚本或映像将来可能会更改,并导致检测代码失败。

我找到了一种通过查找带有404代码的xhrStatus来检测它的方法。另外,我使用JSONP来绕过CORS限制。 404以外的状态代码表示互联网连接无效。

$.ajax({
    url:      'https://www.bing.com/aJyfYidjSlA' + new Date().getTime() + '.html',
    dataType: 'jsonp',
    timeout:  5000,

    error: function(xhr) {
        if (xhr.status == 404) {
            //internet connection working
        }
        else {
            //internet is down (xhr.status == 0)
        }
    }
});

答案 13 :(得分:1)

你可以试试,如果网络已连接,这将返回真

function isInternetConnected(){return navigator.onLine;}

答案 14 :(得分:1)

window.navigator.onLine

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

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

并检查是否在线:

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

答案 15 :(得分:0)

请求头部请求错误

$.ajax({
    url: /your_url,
    type: "POST or GET",
    data: your_data,
    success: function(result){
      //do stuff
    },
    error: function(xhr, status, error) {

      //detect if user is online and avoid the use of async
        $.ajax({
            type: "HEAD",
            url: document.location.pathname,
            error: function() { 
              //user is offline, do stuff
              console.log("you are offline"); 
              }
         });
    }   
});

答案 16 :(得分:0)

诸如navigator.onLine之类的某些方法的问题在于它们与某些浏览器和移动版本不兼容,这对我帮助很大的一个选择是使用经典的XMLHttpRequest方法,并预见了可能的方法。如果文件存储在缓存中且响应XMLHttpRequest.status大于200且小于304。

这是我的代码:

 var xhr = new XMLHttpRequest();
 //index.php is in my web
 xhr.open('HEAD', 'index.php', true);
 xhr.send();

 xhr.addEventListener("readystatechange", processRequest, false);

 function processRequest(e) {
     if (xhr.readyState == 4) {
         //If you use a cache storage manager (service worker), it is likely that the
         //index.php file will be available even without internet, so do the following validation
         if (xhr.status >= 200 && xhr.status < 304) {
             console.log('On line!');
         } else {
             console.log('Offline :(');
         }
     }
}

答案 17 :(得分:0)

对于两种不同的情形,有两个答案: -

  1. 如果您在网站上使用JavaScript(即;或任何前端部分) 最简单的方法是:

      

    <h2>The Navigator Object</h2>
    
    <p>The onLine property returns true if the browser is online:</p>
    
    <p id="demo"></p>
    
    <script>
      document.getElementById("demo").innerHTML = "navigator.onLine is " + navigator.onLine;
    </script>
    

  2. 但如果您在服务器端使用js(即节点等),则可以通过发出失败的XHR请求来确定连接丢失。

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

答案 18 :(得分:0)

我的方式。

<!-- the file named "tt.jpg" should exist in the same directory -->

<script>
function testConnection(callBack)
{
    document.getElementsByTagName('body')[0].innerHTML +=
        '<img id="testImage" style="display: none;" ' +
        'src="tt.jpg?' + Math.random() + '" ' +
        'onerror="testConnectionCallback(false);" ' +
        'onload="testConnectionCallback(true);">';

    testConnectionCallback = function(result){
        callBack(result);

        var element = document.getElementById('testImage');
        element.parentNode.removeChild(element);
    }    
}
</script>

<!-- usage example -->

<script>
function myCallBack(result)
{
    alert(result);
}
</script>

<a href=# onclick=testConnection(myCallBack);>Am I online?</a>

答案 19 :(得分:0)

如果这是navigator.onLine,只需使用true,那么您就在线了,而离线

答案 20 :(得分:0)

如何向 google.com 发送一个不透明的 http 请求并且不带 cors?

    fetch('https://google.com', {
        method: 'GET', // *GET, POST, PUT, DELETE, etc.
        mode: 'no-cors',
    }).then((result) => {
        console.log(result)
    }).catch(e => {
        console.error(e)
    })

设置 no-cors 的原因是,即使在我的电脑上断开网络连接时,我也会收到 cors 错误。所以无论有没有互联网连接,我都被屏蔽了。添加 no-cors 会使请求变得不透明,这似乎绕过了 cors,让我只需检查是否可以连接到 Google。

仅供参考:我在这里使用 fetch 来发出 http 请求。 https://www.npmjs.com/package/fetch

答案 21 :(得分:-3)

这是我有一个帮助程序实用程序的片段。这是命名空间的javascript:

network: function() {
    var state = navigator.onLine ? "online" : "offline";
    return state;
}

你应该在方法检测中使用它,否则就会触发“替代”方法。当这将是所需要的时候,时间快到了。其他方法都是黑客攻击。