How to detect online/offline event cross-browser?

时间秒杀一切 提交于 2019-11-26 01:08:07

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

From the spec:

Returns false if the user agent is definitely offline (disconnected from the network). Returns true if the user agent might be online.

The events online and offline are fired when the value of this attribute changes.

The navigator.onLine attribute must return false if the user agent will not contact the network when the user follows links or when a script requests a remote page (or knows that such an attempt would fail), and must return true otherwise.

Finally, the spec notes:

This attribute is inherently unreliable. A computer can be connected to a network without having Internet access.

The major browser vendors differ on what "offline" means.

Chrome and Safari will detect when you go "offline" automatically - meaning that "online" events and properties will fire automatically when you unplug your network cable.

Firefox (Mozilla), Opera, and IE take a different approach, and consider you "online" unless you explicitly pick "Offline Mode" in the browser - even if you don't have a working network connection.

There are valid arguments for the Firefox/Mozilla behavior, which are outlined in the comments of this bug report:

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.

Instead, you must use alternate approaches.

The "Notes" section of this Mozilla Developer article provides links to two alternate methods:

https://developer.mozilla.org/en/Online_and_offline_events

"If the API isn't implemented in the browser, you can use other signals to detect if you are offline including listening for AppCache error events and responses from XMLHttpRequest"

This links to an example of the "listening for AppCache error events" approach:

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

...and an example of the "listening for XMLHttpRequest failures" approach:

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

HTH, -- Chad

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

Automatically display online/offline indication to your users.

https://github.com/HubSpot/offline

Be sure to check the full README. It contains events that you can hook into.

Here's a test page. It's beautiful/has a nice feedback UI by the way! :)

Offline.js Simulate UI is an Offline.js plug-in that allows you to test how your pages respond to different connectivity states without having to use brute-force methods to disable your actual connectivity.

The best way which works now on all Major Browsers is the following Script:

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

Source: http://robertnyman.com/html5/offline/online-offline-events.html

The window.navigator.onLine attribute and its associated events are currently unreliable on certain web browsers (especially Firefox desktop) as @Junto said, so I wrote a little function (using jQuery) that periodically check the network connectivity status and raise the appropriate offline and online event:

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

You can use it like this:

// 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
}

To listen to the offline and online events (with the help of jQuery):

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

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.

Currently this will represent almost the whole spectrum of users, but you should always check what the users of your page have of capabilities.

Previous to FF 41, it would only show false if the user put the browser manually in offline mode. In IE 8, the property was on the body, instead of window.

source: caniuse

Toolkit

navigator.onLine is a mess

I face this when trying to make an ajax call to the server.

There are several possible situations when the client is offline:

  • the ajax call timouts and you receive error
  • the ajax call returns success, but the msg is null
  • the ajax call is not executed because browser decides so (may be this is when navigator.onLine becomes false after a while)

The solution I am using is to control the status myself with javascript. I set the condition of a successful call, in any other case I assume the client is offline. Something like this:

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

In HTML5 you can use the navigator.onLine property. Look here:

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

Probably your current behavior is random as the javascript only ready the "browser" variable and then knows if you're offline and online, but it doesn't actually check the Network Connection.

Let us know if this is what you're looking for.

Kind Regards,

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

Please read this blog post and let me know your thoughts. http://zen-and-art-of-programming.blogspot.com/2014/04/html-5-offline-application-development.html It contains a code sample using offline.js to detect when the client is offline.

you can detect offline cross-browser way easily like below

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

you can replace yoururl.com by document.location.pathname.

The crux of the solution is, try to connect to your domain name, if you are not able to connect - you are offline. works cross browser.

I use the FALLBACK option in the HTML5 cache manifest to check if my html5 app is online or offline by:

FALLBACK:
/online.txt /offline.txt

In the html page i use javascript tot read the contents of the online/offline txt file:

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

When offline the script will read the contents of the offline.txt. Based on the text in the files you can detect if the webpage is online of offline.

Here is my solution.

Tested with IE, Opera, Chrome, FireFox, Safari, as Phonegap WebApp on IOS 8 and as Phonegap WebApp on Android 4.4.2

This solution isn't working with FireFox on localhost.

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

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'; ?> 

well, you can try the javascript plugin which can monitor the browser connection in real time and notifies the user if internet or the browsers connection with the internet went down.

Wiremonkey Javascript plugin and the demo you can find here

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

Milingu Kilu

Using Document Body:

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

Using Javascript Event:

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

});

Reference:
Document-Body: ononline Event
Javascript-Event: Online and offline events

Additional Thoughts:
To ship around the "network connection is not the same as internet connection" Problem from the above methods: You can check the internet connection once with ajax on the application start and configure an online/offline mode. Create a reconnect button for the user to go online. And add on each failed ajax request a function that kick the user back into the offline mode.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!