繁体   English   中英

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

[英]Detect the Internet connection is offline?

如何在 JavaScript 中检测 Internet 连接离线?

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

标准方法是多次重试请求 如果它没有通过,提醒用户检查连接,并优雅地失败

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

旁注:您可以检查像谷歌这样的可靠网站的连接性,但这可能并不完全有用,因为只是尝试提出您自己的请求,因为虽然谷歌可能可用,但您自己的应用程序可能不可用,而且您仍然会必须处理您自己的连接问题。 尝试向谷歌发送 ping 是确认互联网连接本身已关闭的好方法,因此如果该信息对您有用,那么麻烦就值得了。

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

现在几乎所有主流浏览器都支持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值必然意味着浏览器可以访问 Internet 您可能会得到误报,例如在计算机运行虚拟化软件的情况下,该软件具有始终“连接”的虚拟以太网适配器。 因此,如果你真的想确定浏览器的在线状态,你应该开发额外的检查手段。

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

(重点是我自己)

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

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

我最初打算将此作为对Grant Wagner 答案的更新发布,但似乎编辑太多了,尤其是考虑到 2014 年的更新已经不是他的

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

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

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

更新 (2014/11/16)

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

引自Mozilla 文档

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

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

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

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

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

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

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

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

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

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

window.navigator.onLine

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

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

并检查是否在线:

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

您可以使用$.ajax()error回调,它会在请求失败时触发。 如果textStatus等于字符串“超时”,则可能意味着连接已断开:

function (XMLHttpRequest, textStatus, errorThrown) {
  // typically only one of textStatus or errorThrown 
  // will have info
  this; // the options for this ajax request
}

文档

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

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

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

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

这只是给你的概念,它应该改进。

例如 error=404 应该仍然意味着你在线

我不得不为一个经常与学校合作的客户制作一个网络应用程序(基于 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();
        }
    });
}

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

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;

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

Window.navigator.onLine

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

此选项涉及使用“ window.navigator.onLine ”,这是大多数现代浏览器上可用的浏览器导航器界面下的属性。 它确实不是检查 Internet 可用性的可行选项,因为首先it is browser centric ,其次most browsers implement this property differently 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) 或路由器,则处于离线状态; 所有其他条件返回真。 因此,虽然您可以假设浏览器在返回假值时离线,但您不能假设真值必然意味着浏览器可以访问互联网。 您可能会得到误报,例如在计算机运行虚拟化软件的情况下,该软件具有始终“连接”的虚拟以太网适配器。

上面的陈述只是想让您知道仅靠浏览器是无法分辨的。 所以基本上这个选项是不可靠的。

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

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

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

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

// 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);
  });

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

我们都知道 CORS 是一回事。

此选项涉及向外部服务器资源发出 HTTP 请求,如果可访问,则假定 Internet 可用,否则用户处于离线状态。 对此的主要警告是作为限制的跨源资源共享 大多数信誉良好的网站都会阻止 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。

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

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

向 google.com 发送一个不透明的 http 请求怎么样?

    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

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

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

$.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)
        }
    }
});

我的方式。

<!-- 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>

只需使用navigator.onLine如果这是true那么你在线否则离线

如果网络已连接,您可以尝试这将返回 true

function isInternetConnected(){return navigator.onLine;}

请求头中的请求错误

$.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"); 
              }
         });
    }   
});

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 :(');
         }
     }
}

这是我拥有的辅助实用程序的片段。 这是命名空间的javascript:

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

您应该将其与方法检测一起使用,否则会触发“替代”方法。 时间快到了,这就是所需要的。 其他方法是黑客。

对于两种不同的 senarios 有 2 个答案:-

  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 请求来确定连接丢失。

    标准方法是多次重试请求。 如果它没有通过,提醒用户检查连接,并优雅地失败。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM