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

Posted

技术标签:

【中文标题】检测到互联网连接是不是离线?【英文标题】:Detect the Internet connection is offline?检测到互联网连接是否离线? 【发布时间】:2010-09-16 09:48:21 【问题描述】:

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

【问题讨论】:

如果您可以或已经使用 websockets - websockets 有一个关闭事件,如果用户失去与服务器的连接,则必须调用该事件。 这让我想起了 90 年代,那时你所要做的就是用 image = new Image();image.onload=onloadfunction;image.onerror=onerrorfunction; 然后设置 image.src ="image.gif?"+Math.random();我认为这在今天仍然有效。 【参考方案1】:

Almost all major browsers 现在支持window.navigator.onLine 属性,以及对应的onlineoffline 窗口事件。运行以下代码 sn -p 测试一下:

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 Documentation的这句话:

在 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's answer 的更新发布,但它似乎编辑得太多了,特别是考虑到 2014 年的更新已经是 not from him。

【讨论】:

我最近有机会对离线行为进行了一些研究。这些事件很好用,但是 ios safari 会产生问题。当您在手机上打开互联网时,离线/在线事件最多会延迟 2 秒,由于视觉渲染的原因,这可能会出现问题,因为您无法预测未来。这只是我想提的一点,可能会对某人有所帮助。 当 *** 已连接时,如果我们断开互联网连接,window.navigator.onLine 将不起作用 @Sagar 我检查了 Firefox 和 Chrome,如果我在连接到我的工作 *** 时拔下电缆,它们都会很快检测到断开连接。不过,他们不会等待 *** 重新连接以报告在线状态——正如我在答案中指出的那样,online 只是意味着您有某种连接,而不是您可以访问互联网。我借此机会在我的答案中添加了一个 sn-p 来测试它。 应该选答案! @imike 这取决于提问者,他已经 10 多年没有活动了 :) 我希望能击败公认的答案,但不幸的是 that won’t change their order。【参考方案2】:

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

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

旁注: 将整个应用程序置于“离线”状态可能会导致很多容易出错的状态处理工作。无线连接可能来来去去,等等。所以你最好赌注可能是优雅地失败,保留数据并提醒用户。如果存在连接问题,让他们最终解决连接问题,并在相当宽恕的情况下继续使用您的应用程序。

旁注:您可以检查可靠的网站(如 google)的连接性,但这可能并不完全有用,因为您只是尝试提出自己的请求,因为虽然 Google 可能可用,但您自己的应用程序可能不是,你仍然必须处理自己的连接问题。尝试向 google 发送 ping 是确认 Internet 连接本身已关闭的好方法,因此,如果该信息对您有用,那么这可能是值得的。

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

【讨论】:

现在在 2012 年你可以检查变量 navigator.onLine ;) navigator.online/offline 也不可靠,原因相同。见***.com/questions/3181080/… 您可能想查看Offline.js,这是一个专门为此目的而构建的开源库。 抛开可靠性问题(所有解决方案都存在这个问题),navigator.onLine 绝对是现在最好的it's cross-browser。 "One option is to set up a server-side proxy, wherein we actually ping google (or whatever site), and return the results of the ping to the app"不应将其描述为可能的解决方案来进行检查。即使我已经连接到我的服务器,我也想检查我是否可以访问谷歌,而不是我的服务器。【参考方案3】:

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

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

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

更新(2014 年 11 月 16 日)

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

引用Mozilla Documentation:

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

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

【讨论】:

navigator.onLine 是 html5 的一部分——其他浏览器已经有提供它的开发版本——它已经在今天的 Firefox 3 中可用。 -但很遗憾在早期版本的 IE 中不可用,我们经常需要支持。 navigator.onLine 显示浏览器的状态,而不是实际的连接。所以你可以将你的浏览器设置为onLine,但实际上它会因为连接断开而失败。仅当浏览器设置为离线浏览时,navigator.onLine 才会为 false。 如果我在 Nexus7 上关闭 WI-FI,页面仍然显示 navigator.onLine 为 TRUE。糟糕...【参考方案4】:
 if(navigator.onLine)
  alert('online');
  else 
  alert('offline');
 

【讨论】:

如果在浏览器上,它总是返回 TRUE。 首先我试图只禁用 LAN,但它总是返回 TRUE。因此,当我禁用所有网络(LAN2、Virtual Box 等)时,它返回 FALSE。 这个答案重复了 3 年前的几个现有答案。 它不检查互联网连接,它只检查局域网连接 在 HTML 5、JavaScript、mac book(使用 wifi)中为我工作,甚至在移动设备中工作。但问题是 - 当 wifi 每次都返回 TRUE 时,即使我关闭 wifi,反之亦然。【参考方案5】:

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

AJAX 请求到您自己的网站。如果该请求失败,则很有可能是连接有问题。 JQuery 文档有一个关于 handling failed AJAX requests 的部分。执行此操作时请注意 Same Origin Policy,这可能会阻止您访问域外的网站。 您可以将onerror 放在img 中,例如&lt;img src="http://www.example.com/singlepixel.gif" onerror="alert('Connection dead');" /&gt;

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

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

【讨论】:

【参考方案6】:

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

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

来自doc:

错误:请求时调用的函数 失败。函数通过三个 参数: 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!');
       
   
 );

【讨论】:

【参考方案7】:
window.navigator.onLine

是您要查找的内容,但这里要添加的内容很少,首先,如果它是您想要继续检查的应用程序上的某些内容(例如查看用户是否突然下线,在这种情况下大部分时间都是正确的,那么您还需要监听更改),为此您将事件监听器添加到窗口以检测任何更改,以检查用户是否下线,您可以这样做:

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

以及检查是否在线:

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

【讨论】:

你必须小心onLine。浏览器对在线状态的定义非常不同。看看developer.mozilla.org/en-US/docs/Web/API/NavigatorOnLine/onLine。 此外,这仅在您提出请求时才可靠。只需关闭 wifi 或拔下以太网插头并检查此属性。还是真的。【参考方案8】:

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

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

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

【讨论】:

更新:截至 2015 年,它似乎在大多数浏览器中都可以使用,请参阅 caniuse chart 和 article【参考方案9】:

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

【讨论】:

正如在另一个答案中所讨论的,这实际上并没有按预期工作。你可以没有互联网,navigator.onLine 仍然会返回true【参考方案10】:

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

【讨论】:

【参考方案11】:

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

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

这只是给你一个概念,应该改进。

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

【讨论】:

【参考方案12】:

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

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;

【讨论】:

onLine 并不意味着有互联网连接。根据developer.mozilla.org/en-US/docs/Web/API/NavigatorOnLine/onLineif the browser is not able to connect to a local area network (LAN) or a router, it is offline; all other conditions return true【参考方案13】:

我知道这个问题已经得到解答,但我想加我的 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) 或路由器,则表示处于离线状态;所有其他 条件返回真。所以虽然你可以假设浏览器是 当它返回一个 false 值时离线,你不能假设一个 true 值必然意味着浏览器可以访问互联网。你 可能会出现误报,例如在计算机 正在运行具有虚拟以太网的虚拟化软件 始终“连接”的适配器。

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

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

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

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

这是一个简单的sn-p来获取自己的资源:

// 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 请求,如果可以访问,则假定互联网可用,否则用户离线。对此的主要警告是Cross-origin resource sharing 作为限制。大多数信誉良好的网站都会阻止 CORS 请求,但对于某些网站,您可以随心所欲。

下面是一个简单的sn-p来获取外部资源,与上面相同,但带有外部资源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);
  );

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

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

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

【讨论】:

【参考方案14】:

向 go​​ogle.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

【讨论】:

【参考方案15】:

我的方式。

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

【讨论】:

【参考方案16】:

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

我找到了一种通过查找带有 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)
        
    
);

【讨论】:

这在 2016 年 10 月 5 日不起作用,不知道为什么只是不想浪费其他人的时间。 我不认为它适用于禁止和错误的请求错误:)【参考方案17】:

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

【讨论】:

这在很大程度上是无用的。我从 wifi 断开连接,或者将我的以太网电缆拔到另一台设备上,尽管实际上没有在线,但这个属性仍然是正确的。仍然必须发出失败的 XHR 请求 @DouglasGaskell 哦,我不知道,谢谢纠正我:) @DouglasGaskell 我不同意你所说的。 window.navigator.onLine,这按预期工作。您需要收听online/offline 事件才能看到变化。请查看medium.com/@JackPu/… 或developer.mozilla.org/en-US/docs/Web/API/NavigatorOnLine/onLine 以供参考 @phoenisx 我不确定有什么不同意的?在浏览器中检查此属性,断开 Internet 访问,然后再次检查。这仍然是真的。您链接的文档甚至声明you cannot assume that a true value necessarily means that the browser can access the internet. pmuch 总结了它在检测在线/离线状态时的用处。它还写着if the browser is not able to connect to a local area network (LAN) or a router, it is offline,这再次表明它的用处非常有限。 @DouglasGaskellI 我完全同意你的观点。如果您想非常准确地跟踪互联网连接,它的用例是有限的。尽管在大多数情况下,普通用户不会弄乱他们的网络驱动程序、浏览器首选项或使用 Hypervisor,但对于这种情况,此值(或事件侦听器)是在用户离线时显示一些描述性消息的唯一选项。 【参考方案18】:

你可以试试这个如果网络连接会返回true

function isInternetConnected()return navigator.onLine;

【讨论】:

【参考方案19】:

请求头中的请求错误

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

【讨论】:

【参考方案20】:

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

【讨论】:

【参考方案21】:

这是我拥有的辅助实用程序的 sn-p。这是命名空间的 javascript:

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

您应该将此与方法检测一起使用,否则会触发“替代”方法来执行此操作。时间很快就要到了,这将是我们所需要的一切。其他方法是 hacks。

【讨论】:

【参考方案22】:

对于这两个不同的场景有 2 个答案:-

    如果您在网站上使用 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>
    

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

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

【讨论】:

在网络上在线和有互联网可用是有区别的。

以上是关于检测到互联网连接是不是离线?的主要内容,如果未能解决你的问题,请参考以下文章

如何在基于 c++/QT 的安装程序中检测互联网断开连接

检测离线的gradle脚本功能

检测Android上是不是有可用的互联网连接[重复]

检测用户是不是连接到互联网?

代号一 - “未检测到连接”时的 ToastBar

根据用户离线或在线连接更改链接href