Javascript 是否检测到Internet连接处于脱机状态?

Javascript 是否检测到Internet连接处于脱机状态?,javascript,ajax,offline,connectivity,internet-connection,Javascript,Ajax,Offline,Connectivity,Internet Connection,如何在JavaScript中检测Internet连接处于脱机状态?您可以通过发出失败的XHR请求来确定连接是否丢失 标准方法是重试请求几次。如果没有通过,提醒用户检查连接,然后优雅地失败 旁注:将整个应用程序置于“脱机”状态可能会导致大量易出错的状态处理工作。。无线连接可能会来来去去去,等等。因此,您的最佳选择可能是优雅地失败,保留数据,并提醒用户。。允许他们最终解决连接问题(如果有),并以相当大的宽容继续使用你的应用程序 旁注:你可以检查像谷歌这样可靠的网站的连通性,但这可能不是完全有用的,因

如何在JavaScript中检测Internet连接处于脱机状态?

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

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

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

旁注:你可以检查像谷歌这样可靠的网站的连通性,但这可能不是完全有用的,因为谷歌可能可用,但你自己的应用程序可能不可用,你仍然需要处理自己的连接问题。尝试向谷歌发送ping将是确认互联网连接本身已断开的一个好方法,因此,如果这些信息对您有用,那么可能值得为此付出代价


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

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

  • AJAX请求到您自己的网站。如果该请求失败,很可能是连接出现故障。本文档中有一节介绍。这样做时要小心,这可能会阻止您访问域外的站点
  • 您可以将
    onerror
    放入
    img
    ,如
如果移动/重命名源图像,此方法也可能失败,并且通常比ajax选项更差

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

IE 8将支持该属性

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

在此之前,XHR或
Image()
请求都可以提供接近您所需的功能

更新(2014/11/16)

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

引自:

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

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


HTML5应用程序缓存API指定了navigator.onLine,它目前在IE8 betas、WebKit(如Safari)夜间版中可用,并且在Firefox 3中已经得到支持。您可以使用的
错误
回调,如果请求失败,它将触发。如果
textStatus
等于字符串“timeout”,则可能表示连接中断:

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

错误:如果请求 失败。函数传递三次 参数: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!');
       }
   }
 });

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

最近,WHATWG已指定添加
在线
离线
事件,以防您需要对
导航器.在线
更改做出反应

也请注意
network: function() {
    var state = navigator.onLine ? "online" : "offline";
    return state;
}
<!-- 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>
 if(navigator.onLine){
  alert('online');
 } else {
  alert('offline');
 }
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();
        }
    });
}
$.ajax({
      type: "HEAD",
      url: document.location.pathname + "?param=" + new Date(),
      error: function() { return false; },
      success: function() { return true; }
   });
$.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)
        }
    }
});
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;
<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>
$.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"); 
              }
         });
    }   
});
 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 :(');
         }
     }
}
window.navigator.onLine
window.addEventListener("offline", 
  ()=> console.log("No Internet")
);
window.addEventListener("online", 
  ()=> console.log("Connected Internet")
);
// 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);
  });
// 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);
  });
function isInternetConnected(){return navigator.onLine;}
    fetch('https://google.com', {
        method: 'GET', // *GET, POST, PUT, DELETE, etc.
        mode: 'no-cors',
    }).then((result) => {
        console.log(result)
    }).catch(e => {
        console.error(e)
    })