如何检测跨浏览器的在线/离线事件?

时间:2010-07-05 16:53:08

标签: javascript jquery javascript-events offline network-connection

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

14 个答案:

答案 0 :(得分:64)

浏览器供应商无法就如何定义离线达成一致。有些浏览器具有脱机工作功能,他们认为这与缺乏网络访问是分开的,这与互联网访问不同。整件事情一团糟。某些浏览器供应商在实际网络访问丢失时更新navigator.onLine标志,而其他浏览器供应商则不会。

来自规范:

  

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

     

在线和离线的活动是   在此属性的值时触发   变化。

     

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

最后,规范指出:

  

此属性本质上是   不可靠的。电脑可以   没有连接到网络   互联网接入。

答案 1 :(得分:31)

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

Chrome和Safari会自动检测您何时“离线” - 这意味着当您拔下网络电缆时,“在线”事件和属性会自动触发。

Firefox(Mozilla),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, - 乍得

答案 2 :(得分:18)

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

  

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

https://github.com/HubSpot/offline

请务必查看完整的README。它包含您可以挂钩的事件。

这里是test page。它的美丽/顺便说一句,有很好的反馈用户界面! :)

  

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

答案 3 :(得分:15)

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

(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

答案 4 :(得分:9)

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

// Global variable somewhere in your app to replicate the 
// window.navigator.onLine variable (it 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');
  }
});

答案 5 :(得分:9)

最近,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

答案 6 :(得分:6)

navigator.onLine是一团糟

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

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

  • ajax呼叫时钟,您收到错误
  • ajax调用返回成功,但msg为null
  • ajax调用未执行,因为浏览器决定(可能是这时navigator.onLine在一段时间后变为false)

我使用的解决方案是使用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);
          }
        });
      }

答案 7 :(得分:5)

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

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

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

如果您正在寻找,请告诉我们。

亲切的问候,

答案 8 :(得分:2)

请找到我为脱机编写的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检测客户端何时脱机的代码示例。

答案 9 :(得分:2)

您可以轻松地检测离线跨浏览器方式,如下所示

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。

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

答案 10 :(得分:2)

我使用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的内容。 根据文件中的文本,您可以检测网页是否处于脱机状态。

答案 11 :(得分:0)

这是我的解决方案。

使用IE,Opera,Chrome,FireFox,Safari,IOS 8上的Phonegap WebApp和Android 4.4.2上的Phonegap WebApp进行测试

此解决方案无法在localhost上使用FireFox。

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

onlineCheck.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;

    }
}

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

index.html(filepath:“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(filepath:“root”):

<?php echo 'true'; ?> 

答案 12 :(得分:0)

好吧,您可以尝试javascript插件,它可以实时监控浏览器连接,并通知用户互联网或浏览器与互联网的连接是否已关闭。

Wiremonkey Javascript plugin 和你可以在这里找到的演示

  

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

答案 13 :(得分:0)

使用文档正文

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事件:

$(this)

参考的:
文件正文:CreateTextFile Method
Javascript-Event:ononline Event

其他想法:
运输“网络连接与互联网连接不同”上述方法存在问题:您可以在应用程序启动时使用ajax检查互联网连接一次,并配置在线/离线模式。创建一个重新连接按钮,供用户上线。并在每个失败的ajax请求上添加一个功能,使用户重新进入离线模式。

相关问题