如何在 JavaScript 中检测 Internet 连接是否脱机?
22 回答
现在几乎所有主流浏览器都支持该window.navigator.onLine
属性,以及相应的online
和offline
窗口事件。运行以下代码片段来测试它:
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
值必然意味着浏览器可以访问互联网。您可能会得到误报,例如在计算机运行具有始终“连接”的虚拟以太网适配器的虚拟化软件的情况下。因此,如果你真的想确定浏览器的在线状态,你应该开发额外的检查手段。在 Firefox 和 Internet Explorer 中,将浏览器切换到离线模式会发送一个
false
值。在 Firefox 41 之前,所有其他条件都返回一个true
值;从 Firefox 41 开始,在 OS X 和 Windows 上,该值将遵循实际的网络连接。
(重点是我自己的)
这意味着如果window.navigator.onLine
是false
(或您收到offline
事件),则保证您没有 Internet 连接。
但是,如果是true
(或您收到online
事件),则最多仅意味着系统已连接到某个网络。例如,这并不意味着您可以访问 Internet。要检查这一点,您仍然需要使用其他答案中描述的解决方案之一。
您可以通过发出失败的 XHR 请求来确定连接已丢失。
标准方法是重试请求几次。如果没有通过,提醒用户检查连接,并优雅地失败。
旁注:将整个应用程序置于“离线”状态可能会导致很多容易出错的状态处理工作。无线连接可能来来去去,等等。所以你最好的选择可能是优雅地失败,保留数据,并提醒用户。如果存在连接问题,允许他们最终解决连接问题,并在相当宽恕的情况下继续使用您的应用程序。
旁注:您可以检查像 google 这样的可靠站点的连接性,但这可能并不完全有用,因为只是尝试提出您自己的请求,因为虽然 Google 可能可用,但您自己的应用程序可能不可用,而且您仍然会必须处理自己的连接问题。尝试向 google 发送 ping 将是确认 Internet 连接本身已关闭的好方法,因此如果该信息对您有用,那么它可能是值得的。
旁注:发送 Ping的方式与发出任何双向 ajax 请求的方式相同,但在这种情况下,向 google 发送 ping 会带来一些挑战。首先,我们会遇到在进行 Ajax 通信时通常会遇到的相同的跨域问题。一种选择是设置服务器端代理,我们实际上在其中ping
搜索(或任何网站),并将 ping 的结果返回给应用程序。这是第 22 条因为如果互联网连接确实是问题,我们将无法访问服务器,如果连接问题仅在我们自己的域上,我们将无法区分。可以尝试其他跨域技术,例如,在指向 google.com 的页面中嵌入 iframe,然后轮询 iframe 以了解成功/失败(检查内容等)。嵌入图像可能并不能真正告诉我们任何事情,因为我们需要来自通信机制的有用响应,以便对正在发生的事情得出一个好的结论。同样,确定整个互联网连接的状态可能比它的价值更麻烦。您必须为您的特定应用权衡这些选项。
IE 8 将支持window.navigator.onLine属性。
但这当然对其他浏览器或操作系统没有帮助。鉴于了解 Ajax 应用程序中在线/离线状态的重要性,我预测其他浏览器供应商也将决定提供该属性。
在此之前,XHR 或Image()
or<img>
请求都可以提供接近您想要的功能的东西。
更新 (2014/11/16)
现在主流浏览器都支持这个属性,但是你的结果会有所不同。
引自Mozilla 文档:
在 Chrome 和 Safari 中,如果浏览器无法连接到局域网 (LAN) 或路由器,则它处于离线状态;所有其他条件返回
true
。因此,虽然您可以假设浏览器在返回false
值时处于脱机状态,但您不能假设真正的值必然意味着浏览器可以访问互联网。您可能会得到误报,例如在计算机运行具有始终“连接”的虚拟以太网适配器的虚拟化软件的情况下。因此,如果你真的想确定浏览器的在线状态,你应该开发额外的检查手段。在 Firefox 和 Internet Explorer 中,将浏览器切换到离线模式会发送一个
false
值。所有其他条件都返回一个true
值。
有多种方法可以做到这一点:
- AJAX 请求到您自己的网站。如果该请求失败,则很有可能是连接有问题。JQuery文档有一节处理失败的AJAX 请求。执行此操作时请注意同源策略,这可能会阻止您访问域外的站点。
- 你可以把一个
onerror
,img
像<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 已指定添加online
和offline
事件,以防您需要对navigator.onLine
更改做出反应。
还请注意 Daniel Silveira 发布的链接,该链接指出依赖这些信号/属性与服务器同步并不总是一个好主意。
您可以使用$.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
}
从文档:
错误:请求失败时调用的函数。该函数被传递三个参数: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!');
}
}
});
window.navigator.onLine
是您要查找的内容,但这里要添加的内容很少,首先,如果它是您想要继续检查的应用程序上的某些内容(例如查看用户是否突然离线,在这种情况下大多数情况下都是正确的,那么您还需要收听更改),为此您将事件侦听器添加到窗口以检测任何更改,以检查用户是否下线,您可以执行以下操作:
window.addEventListener("offline",
()=> console.log("No Internet")
);
并检查是否在线:
window.addEventListener("online",
()=> console.log("Connected Internet")
);
HTML5 应用程序缓存 API 指定了 navigator.onLine,它目前在 IE8 测试版、WebKit(例如 Safari)nightlies 中可用,并且已在 Firefox 3 中得到支持
我必须为一个经常与学校合作的客户制作一个网络应用程序(基于 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();
}
});
}
对您的域进行 ajax 调用是检测您是否离线的最简单方法
$.ajax({
type: "HEAD",
url: document.location.pathname + "?param=" + new Date(),
error: function() { return false; },
success: function() { return true; }
});
这只是给你的概念,应该改进。
eg error=404 应该仍然意味着你在线
我认为这是一个非常简单的方法。
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 ”,这是大多数现代浏览器上可用的 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。因此,虽然您可以假设浏览器在返回 false 值时处于脱机状态,但您不能假设 true 值必然意味着浏览器可以访问互联网。您可能会得到误报,例如在计算机运行具有始终“连接”的虚拟以太网适配器的虚拟化软件的情况下。
上面的陈述只是想让您知道仅凭浏览器无法分辨。所以基本上这个选项是不可靠的。
向自己的服务器资源发送请求
这涉及向您自己的服务器资源发出 HTTP 请求,如果可以访问,则假定 Internet 可用性,否则用户处于脱机状态。此选项有一些注意事项。- 没有服务器可用性是 100% 依赖的,因此如果由于某种原因您的服务器无法访问,则会错误地假定用户在连接到 Internet 时处于离线状态。
- 对同一资源的多个请求可能会返回缓存的响应,从而使 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 可用性,否则用户处于脱机状态。对此的主要警告是作为限制的跨域资源共享。大多数信誉良好的网站都会阻止 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。
请记住,您的用户也可能处于某些网站或资源被阻止、禁止且无法访问的环境中,这反过来会影响连接检查的逻辑。最好的选择是:
- 尝试访问您自己服务器上的资源,因为这是您的用户环境(通常我使用网站的图标,因为响应非常轻且不经常更新)。
- 如果没有与资源的连接,只需在需要通知用户时说“连接错误”或“连接丢失”,而不是假设一个广泛的“没有互联网连接”,这取决于许多因素。
我的方式。
<!-- 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>
我正在寻找一种客户端解决方案来检测互联网是否已关闭或我的服务器是否已关闭。我发现的其他解决方案似乎总是依赖于第 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)
}
}
});
如何使用 no-cors 向 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
只需使用navigator.onLine
if this is true
then you're online else offline
如果网络连接,您可以尝试这将返回 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;
}
您应该将此与方法检测一起使用,否则会触发一种“替代”方式来执行此操作。时间很快就要到了,这将是我们所需要的一切。其他方法是黑客。
对于两个不同的场景,有 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 请求来确定连接丢失。
标准方法是重试请求几次。如果它没有通过,提醒用户检查连接,并优雅地失败。