如何跨浏览器检测联机/脱机事件?

我试图通过使用 HTML5的在线和离线事件来准确检测浏览器什么时候离线。

这是我的密码:

<script>
// FIREFOX
$(window).bind("online", applicationBackOnline);
$(window).bind("offline", applicationOffline);


//IE
window.onload = function() {
document.body.ononline = IeConnectionEvent;
document.body.onoffline = IeConnectionEvent;
}
</script>

当我在 Firefox 或者 IE 上点击“脱机工作”时,它工作得很好,但是当我真正拔掉电线的时候,它就会随机工作。

检测这种变化的最佳方法是什么? 我希望避免使用超时重复 Ajax 调用。

134685 次浏览

在 HTML5中你可以使用 navigator.onLine属性,看这里:

Http://www.w3.org/tr/offline-webapps/#related

可能你当前的行为是随机的,因为 javascript 只准备了“浏览器”变量,然后知道你是否离线和在线,但它实际上并没有检查网络连接。

告诉我们这是不是你要找的。

致以亲切的问候,

Currently in 2011, the various browser vendors cannot agree on how to define offline. Some browsers have a Work Offline feature, which they consider separate to a lack of network access, which again is different to internet access. The whole thing is a mess. Some browser vendors update the navigator.onLine flag when actual network access is lost, others don't.

规格说明:

如果用户代理为 definitely offline (disconnected from 网络)。如果用户 探员可能在线。

在线和离线是 fired when the value of this attribute 改变。

OnLine 属性必须 return false if the user agent will 用户不联系网络时 跟随链接或当脚本 请求远程页面(或者知道 这种尝试将会失败) ,而且必须 否则返回 true。

最后,规范指出:

这个属性本质上是 不可靠。计算机可以 连接到一个网络,而没有 上网。

导航员,网上一团糟

我在尝试向服务器调用 ajax 时遇到了这个问题。

当客户端离线时有几种可能的情况:

  • Ajax 调用超时,您将收到错误
  • Ajax 调用返回成功,但 msg 为空
  • the ajax call is not executed because browser decides so (may be this is when navigator.onLine becomes false after a while)

我使用的解决方案是用 javascript 自己控制状态。我设置了一个成功调用的条件,在其他情况下,我假设客户端离线。 就像这样:

var offline;
pendingItems.push(item);//add another item for processing
updatePendingInterval = setInterval("tryUpdatePending()",30000);
tryUpdatePending();


function tryUpdatePending() {


offline = setTimeout("$('#offline').show()", 10000);
$.ajax({ data: JSON.stringify({ items: pendingItems }), url: "WebMethods.aspx/UpdatePendingItems", type: "POST", dataType: "json", contentType: "application/json; charset=utf-8",
success: function (msg) {
if ((!msg) || msg.d != "ok")
return;
pending = new Array(); //empty the pending array
$('#offline').hide();
clearTimeout(offline);
clearInterval(updatePendingInterval);
}
});
}

主要的浏览器供应商对“脱机”的含义存在分歧。

Chrome、 Safari 和 Firefox (自41版以来)会自动检测你何时“脱机”——也就是说,当你拔掉网线时,“在线”事件和属性会自动触发。

Mozilla Firefox (41版之前)、 Opera 和 IE 采取了不同的方式,认为你是“在线”的,除非你在浏览器中明确选择“离线模式”——即使你没有工作的网络连接。

对于 Firefox/Mozilla 的行为,有一些有效的论据,这些论据在这个 bug 报告的评论中有所概述:

Https://bugzilla.mozilla.org/show_bug.cgi?id=654579

But, to answer the question - you can't rely on the online/offline events/property to detect if there is actually network connectivity.

相反,您必须使用其他方法。

Mozilla Developer 文章的“ Notes”部分提供了两种替代方法的链接:

Https://developer.mozilla.org/en/online_and_offline_events

如果该 API 没有在浏览器中实现,您可以使用其他信号来检测是否脱机,包括监听 AppCache 错误事件和来自 XMLHttpRequest 的响应

这个链接到一个“监听 AppCache 错误事件”方法的例子:

Http://www.html5rocks.com/en/mobile/workingoffthegrid/#toc-appcache

以及“监听 XMLHttpRequest 失败”方法的一个例子:

http://www.html5rocks.com/en/mobile/workingoffthegrid/#toc-xml-http-request

HTH, 查德

现在在所有主要浏览器上工作的最佳方式是下面的脚本:

(function () {
var displayOnlineStatus = document.getElementById("online-status"),
isOnline = function () {
displayOnlineStatus.innerHTML = "Online";
displayOnlineStatus.className = "online";
},
isOffline = function () {
displayOnlineStatus.innerHTML = "Offline";
displayOnlineStatus.className = "offline";
};


if (window.addEventListener) {
/*
Works well in Firefox and Opera with the
Work Offline option in the File menu.
Pulling the ethernet cable doesn't seem to trigger it.
Later Google Chrome and Safari seem to trigger it well
*/
window.addEventListener("online", isOnline, false);
window.addEventListener("offline", isOffline, false);
}
else {
/*
Works in IE with the Work Offline option in the
File menu and pulling the ethernet cable
*/
document.body.ononline = isOnline;
document.body.onoffline = isOffline;
}
})();

资料来源: http://robertnyman.com/html5/offline/online-offline-events.html

Please find the require.js module that I wrote for Offline.

define(['offline'], function (Offline) {
//Tested with Chrome and IE11 Latest Versions as of 20140412
//Offline.js - http://github.hubspot.com/offline/
//Offline.js is a library to automatically alert your users
//when they've lost internet connectivity, like Gmail.
//It captures AJAX requests which were made while the connection
//was down, and remakes them when it's back up, so your app
//reacts perfectly.


//It has a number of beautiful themes and requires no configuration.
//Object that will be exposed to the outside world. (Revealing Module Pattern)


var OfflineDetector = {};


//Flag indicating current network status.
var isOffline = false;


//Configuration Options for Offline.js
Offline.options = {
checks: {
xhr: {
//By default Offline.js queries favicon.ico.
//Change this to hit a service that simply returns a 204.
url: 'favicon.ico'
}
},


checkOnLoad: true,
interceptRequests: true,
reconnect: true,
requests: true,
game: false
};


//Offline.js raises the 'up' event when it is able to reach
//the server indicating that connection is up.
Offline.on('up', function () {
isOffline = false;
});


//Offline.js raises the 'down' event when it is unable to reach
//the server indicating that connection is down.
Offline.on('down', function () {
isOffline = true;
});


//Expose Offline.js instance for outside world!
OfflineDetector.Offline = Offline;


//OfflineDetector.isOffline() method returns the current status.
OfflineDetector.isOffline = function () {
return isOffline;
};


//start() method contains functionality to repeatedly
//invoke check() method of Offline.js.
//This repeated call helps in detecting the status.
OfflineDetector.start = function () {
var checkOfflineStatus = function () {
Offline.check();
};
setInterval(checkOfflineStatus, 3000);
};


//Start OfflineDetector
OfflineDetector.start();
return OfflineDetector;
});

请阅读这篇博文,让我知道你的想法。它包含一个使用 offline.js 检测客户机离线时间的代码示例。

Today there's an open source JavaScript library that does this job: it's called Offline.js.

自动向用户显示联机/脱机指示。

https://github.com/HubSpot/offline

一定要检查完整的 自述。它包含你可以挂钩到的事件。

这是一个 测试页。它很漂亮/顺便说一下,它有一个很好的反馈用户界面! :)

模拟用户界面是一个 Offline.js 插件 它允许您测试页面如何响应不同的 连接状态,而不必使用强力方法 切断你的实际连接。

这是我的解决办法。

测试了 IE,Opera,Chrome,FireFox,Safari,在 IOS 8上作为 Phonegap WebApp,在 Android 4.4.2上作为 Phonegap WebApp

这个解决方案不能在本地主机上使用 FireFox。

=================================================================================

Js (filepath: “ root/js/onlineCheck.js) :

var isApp = false;


function onLoad() {
document.addEventListener("deviceready", onDeviceReady, false);
}


function onDeviceReady() {
isApp = true;
}




function isOnlineTest() {
alert(checkOnline());
}


function isBrowserOnline(no,yes){
//Didnt work local
//Need "firefox.php" in root dictionary
var xhr = XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHttp');
xhr.onload = function(){
if(yes instanceof Function){
yes();
}
}
xhr.onerror = function(){
if(no instanceof Function){
no();
}
}
xhr.open("GET","checkOnline.php",true);
xhr.send();
}


function checkOnline(){


if(isApp)
{
var xhr = new XMLHttpRequest();
var file = "http://dexheimer.cc/apps/kartei/neu/dot.png";


try {
xhr.open('HEAD', file , false);
xhr.send(null);


if (xhr.status >= 200 && xhr.status < 304) {
return true;
} else {
return false;
}
} catch (e)
{
return false;
}
}else
{
var tmpIsOnline = false;


tmpIsOnline = navigator.onLine;


if(tmpIsOnline || tmpIsOnline == "undefined")
{
try{
//Didnt work local
//Need "firefox.php" in root dictionary
var xhr = XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHttp');
xhr.onload = function(){
tmpIsOnline = true;
}
xhr.onerror = function(){
tmpIsOnline = false;
}
xhr.open("GET","checkOnline.php",false);
xhr.send();
}catch (e){
tmpIsOnline = false;
}
}
return tmpIsOnline;


}
}

=================================================================================

.html (文件路径: “ root/index.html”) :

<!DOCTYPE html>
<html>




<head>
...


<script type="text/javascript" src="js/onlineCheck.js" ></script>


...


</head>


...


<body onload="onLoad()">


...


<div onclick="isOnlineTest()">
Online?
</div>
...
</body>


</html>

=================================================================================

Php (文件路径: “ root”) :

<?php echo 'true'; ?>

正如@Junto 所说,window.navigator.onLine属性及其相关事件目前在某些 Web 浏览器(尤其是 Firefox 桌面)上是不可靠的,因此我编写了一个小函数(使用 jQuery) ,定期检查网络连接状态并引发适当的 offlineonline事件:

// Global variable somewhere in your app to replicate the
// window.navigator.onLine variable (this last is not modifiable). It prevents
// the offline and online events to be triggered if the network
// connectivity is not changed
var IS_ONLINE = true;


function checkNetwork() {
$.ajax({
// Empty file in the root of your public vhost
url: '/networkcheck.txt',
// We don't need to fetch the content (I think this can lower
// the server's resources needed to send the HTTP response a bit)
type: 'HEAD',
cache: false, // Needed for HEAD HTTP requests
timeout: 2000, // 2 seconds
success: function() {
if (!IS_ONLINE) { // If we were offline
IS_ONLINE = true; // We are now online
$(window).trigger('online'); // Raise the online event
}
},
error: function(jqXHR) {
if (jqXHR.status == 0 && IS_ONLINE) {
// We were online and there is no more network connection
IS_ONLINE = false; // We are now offline
$(window).trigger('offline'); // Raise the offline event
} else if (jqXHR.status != 0 && !IS_ONLINE) {
// All other errors (404, 500, etc) means that the server responded,
// which means that there are network connectivity
IS_ONLINE = true; // We are now online
$(window).trigger('online'); // Raise the online event
}
}
});
}

你可以这样使用它:

// Hack to use the checkNetwork() function only on Firefox
// (http://stackoverflow.com/questions/5698810/detect-firefox-browser-with-jquery/9238538#9238538)
// (But it may be too restrictive regarding other browser
// who does not properly support online / offline events)
if (!(window.mozInnerScreenX == null)) {
window.setInterval(checkNetwork, 30000); // Check the network every 30 seconds
}

要侦听离线和在线事件(借助 jQuery) :

$(window).bind('online offline', function(e) {
if (!IS_ONLINE || !window.navigator.onLine) {
alert('We have a situation here');
} else {
alert('Battlestation connected');
}
});

你可以像下面这样方便地检测离线跨浏览器

var randomValue = Math.floor((1 + Math.random()) * 0x10000)


$.ajax({
type: "HEAD",
url: "http://yoururl.com?rand=" + randomValue,
contentType: "application/json",
error: function(response) { return response.status == 0; },
success: function() { return true; }
});

你可以用 document.location.pathname代替 yoururl.com。

解决这个问题的关键是,如果你不能连接到你的域名,那么尝试连接到你的域名——你离线了。跨浏览器工作。

我使用 HTML5缓存清单中的 FALLBack 选项来检查我的 html5应用程序是在线还是离线,方法是:

FALLBACK:
/online.txt /offline.txt

在 html 页面中,我使用 javascript tot 读取在线/离线 txt 文件的内容:

<script>$.get( "urlto/online.txt", function( data ) {
$( ".result" ).html( data );
alert( data );
});</script>

当脱机时,脚本将读取 offline.txt 的内容。 Based on the text in the files you can detect if the webpage is online of offline.

Since recently, navigator.onLine shows the same on all major browsers, and is thus useable.

if (navigator.onLine) {
// do things that need connection
} else {
// do things that don't need connection
}

The oldest versions that support this in the right way are: Firefox 41, IE 9, Chrome 14 and Safari 5.

目前,这将代表几乎所有的用户,但是您应该始终检查您的页面的用户具有哪些功能。

在 FF 41之前,只有当用户手动将浏览器置于脱机模式时,它才会显示 false。在 IE8中,属性位于 body,而不是 window

来源: 犬科动物

嗯,你可以试试 javascript 插件,它可以实时监控浏览器连接,并通知用户如果互联网或浏览器与互联网连接中断。

WireMonkey Javascript 插件 你可以在这里找到演示

Http://ryvan-js.github.io/

Using Document Body:

<body ononline="onlineConditions()" onoffline="offlineConditions()">(...)</body>

使用 Javascript 事件:

window.addEventListener('load', function() {


function updateOnlineStatus() {


var condition = navigator.onLine ? "online" : "offline";
if( condition == 'online' ){
console.log( 'condition: online')
}else{
console.log( 'condition: offline')
}


}


window.addEventListener('online',  updateOnlineStatus );
window.addEventListener('offline', updateOnlineStatus );


});

参考 :
文件正文: 在线活动
Javascript-Event: < a href = “ https://developer.mozilla.org/en-US/docs/Online _ and _ off _ events”rel = “ nofollow noReferrer”> 在线和离线事件

其他想法:
要绕过“网络连接不同于互联网连接”的问题,从以上方法中可以看出: 您可以在应用程序启动时用 ajax 检查一次互联网连接,然后配置一个在线/离线模式。为用户创建一个重新连接按钮以便联机。并在每个失败的 ajax 请求上添加一个函数,将用户踢回脱机模式。

<html>
<head>
<script>
window.addEventListener("online",function(){
document.getElementById('note').
innerHTML='you are online';
});
window.addEventListener("offline",function(){
document.getElementById('note').
innerHTML='you are offline';
});
</script>
</head>
<body>
<div id="note"> </div>
</body>
</html>