115

我正在尝试使用 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调用。

4

14 回答 14

72

目前在 2011 年,各个浏览器厂商对于如何定义离线还不能达成一致。一些浏览器具有离线工作功能,他们认为这与缺乏网络访问是分开的,这又与互联网访问不同。整个事情是一团糟。一些浏览器供应商会在实际网络访问丢失时更新 navigator.onLine 标志,而其他浏览器供应商则不会。

从规范:

如果用户代理确实离线(与网络断开连接),则返回 false。如果用户代理可能在线,则返回 true。

当该属性的值改变时,会触发在线和离线事件。

如果当用户点击链接或脚本请求远程页面(或知道这样的尝试将失败)时用户代理不会联系网络,则 navigator.onLine 属性必须返回 false,否则必须返回 true。

最后,规范说明:

这个属性本质上是不可靠的。计算机可以连接到网络而无需访问 Internet。

于 2011-01-27T06:30:22.317 回答
34

主要浏览器供应商对“离线”的含义有所不同。

Chrome、Safari 和 Firefox(自 41 版起)会自动检测您何时“离线”——这意味着当您拔下网络电缆时“在线”事件和属性将自动触发。

Mozilla Firefox(版本 41 之前)、Opera 和 IE 采用不同的方法,除非您在浏览器中明确选择“离线模式”,否则会将您视为“在线”——即使您没有可用的网络连接。

Firefox/Mozilla 的行为有一些有效的论据,在这个错误报告的评论中概述:

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

但是,要回答这个问题 - 您不能依靠在线/离线事件/属性来检测是否确实存在网络连接。

相反,您必须使用替代方法。

这篇 Mozilla 开发者文章的“注释”部分提供了两种替代方法的链接:

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,--乍得

于 2012-03-13T02:19:54.057 回答
17

今天有一个开源的 JavaScript 库可以完成这项工作:它被称为Offline.js.

自动向您的用户显示在线/离线指示。

https://github.com/HubSpot/offline

请务必检查完整的自述文件。它包含您可以挂钩的事件。

这是一个测试页。顺便说一句,它很漂亮/有一个很好的反馈 UI!:)

Offline.js Simulate UI 是一个 Offline.js 插件,它允许您测试您的页面如何响应不同的连接状态,而无需使用暴力方法来禁用您的实际连接。

于 2014-05-28T05:03:31.477 回答
16

现在适用于所有主要浏览器的最佳方式是以下脚本:

(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

于 2013-08-23T10:39:57.493 回答
15

从最近开始,navigator.onLine在所有主要浏览器上显示相同,因此可用。

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

以正确方式支持此功能的最旧版本是:Firefox 41、IE 9、Chrome 14 和 Safari 5。

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

在 FF 41 之前,它只会显示false用户是否手动将浏览器置于离线模式。在 IE 8 中,该属性位于body,而不是window.

来源:caniuse

于 2016-04-01T11:04:21.657 回答
13

正如@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');
  }
});
于 2015-02-17T09:11:15.797 回答
7

navigator.onLine 是一团糟

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

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

  • ajax 调用超时,您收到错误
  • ajax 调用返回成功,但 msg 为空
  • ajax调用没有被执行,因为浏览器决定这样做(可能是navigator.onLine在一段时间后变为假)

我正在使用的解决方案是使用 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);
          }
        });
      }
于 2011-06-22T02:25:09.390 回答
5

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

http://www.w3.org/TR/offline-webapps/#related

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

让我们知道这是否是您正在寻找的。

亲切的问候,

于 2010-07-05T16:59:09.777 回答
3

请找到我为 Offline 编写的 require.js 模块。

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

请阅读这篇博文,让我知道你的想法。http://zen-and-art-of-programming.blogspot.com/2014/04/html-5-offline-application-development.html它包含一个代码示例,使用offline.js 来检测客户端何时离线。

于 2014-04-15T11:48:48.730 回答
3

您可以像下面这样轻松检测离线跨浏览器的方式

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

您可以将 yoururl.com 替换为document.location.pathname.

解决方案的关键是,尝试连接到您的域名,如果您无法连接 - 您处于离线状态。跨浏览器工作。

于 2015-04-22T09:24:17.057 回答
2

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

FALLBACK:
/online.txt /offline.txt

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

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

离线时,脚本将读取offline.txt 的内容。根据文件中的文本,您可以检测网页是在线还是离线。

于 2016-03-08T15:46:22.877 回答
1

使用文档正文:

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

});

参考:
Document-Body: ononline Event
Javascript-Event:在线和离线事件

附加想法:
解决“网络连接与互联网连接不同”的问题 上述方法的问题:您可以在应用程序启动时使用 ajax 检查一次互联网连接并配置在线/离线模式。为用户上线创建一个重新连接按钮。并在每个失败的 ajax 请求上添加一个将用户踢回离线模式的功能。

于 2017-01-25T11:15:22.743 回答
0

这是我的解决方案。

通过 IE、Opera、Chrome、FireFox、Safari 测试,作为 IOS 8 上的 Phonegap WebApp 和 Android 4.4.2 上的 Phonegap WebApp

此解决方案不适用于本地主机上的 FireFox。

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

onlineCheck.js(文件路径:“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;

    }
}

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

index.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>

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

checkOnline.php(文件路径:“根”):

<?php echo 'true'; ?> 
于 2014-09-30T09:50:40.770 回答
0

好吧,你可以试试javascript插件,它可以实时监控浏览器连接,并在互联网或浏览器与互联网的连接出现故障时通知用户。

您可以在此处找到Wiremonkey Javascript 插件和演示

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

于 2016-06-29T03:05:06.577 回答