Come rilevare eventi online / offline cross-browser?


111

Sto cercando di rilevare con precisione quando il browser va offline, utilizzando gli eventi online e offline HTML5.

Ecco il mio codice:

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

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

Funziona bene quando ho appena premuto "Lavora offline" su Firefox o IE, ma funziona in modo casuale quando scollego il cavo.

Qual è il modo migliore per rilevare questo cambiamento? Vorrei evitare di ripetere le chiamate Ajax con timeout.


2
Sono d'accordo con Trefex, ma vorrei anche aggiungere che il supporto per il rilevamento della connessione è scadente nella migliore delle ipotesi per la maggior parte delle app: solo perché il cavo è scollegato non costituisce immediatamente una connessione persa. Affidarsi a un metodo che non verifica fisicamente se la connessione è aperta non può garantire risultati accurati.
mattbasta

Grazie per il tuo consiglio. Quindi consiglieresti il ​​metodo Ajax? vale a dire. continuare a inviare chiamate XHR con timeout?
Pierre Duplouy

L'implementazione di Firefox (e IE e Opera) è sbagliata. Vedi il mio commento in tal senso qui: bugzilla.mozilla.org/show_bug.cgi?id=654579#c9
thewoolleyman

4
Potresti voler controllare Offline.js , una libreria open source creata proprio per questo scopo.
Adam

Risposte:


70

I fornitori di browser non sono d'accordo su come definire offline. Alcuni browser hanno una funzione Lavora offline, che considerano separata dalla mancanza di accesso alla rete, che è di nuovo diversa dall'accesso a Internet. L'intera cosa è un casino. Alcuni fornitori di browser aggiornano il flag navigator.onLine quando si perde l'accesso effettivo alla rete, altri no.

Dalle specifiche:

Restituisce falso se il programma utente è decisamente offline (disconnesso dalla rete). Restituisce vero se l'agente utente potrebbe essere in linea.

Gli eventi online e offline vengono generati quando il valore di questo attributo cambia.

L'attributo navigator.onLine deve restituire false se l'agente utente non contatterà la rete quando l'utente segue i collegamenti o quando uno script richiede una pagina remota (o sa che un tale tentativo fallirebbe) e deve restituire true altrimenti.

Infine, le note specifiche:

Questo attributo è intrinsecamente inaffidabile. Un computer può essere connesso a una rete senza avere accesso a Internet.


23
Solo Chrome imposta correttamente navigator.onLine quando la connettività viene persa. Sia Safari che Firefox non impostano mai il flag su false se rimuovi la connessione Internet.
chovy

2
@chovy e adesso? Recentemente l'ho testato in Firefox / Chrome e ho ottenuto i risultati attesi, visto che il flag è in fase di impostazione, quando spengo e accendo la connessione internet ..
James Cazzetta

12
Oggi 31/1/2017 ho aperto OSX Chrome 55.0.2883.95, Safari 10.0.3 e FF 50.1.0. Tutto il window.navigator.onLine sembra funzionare alla grande quando sono rimasto sulla mia rete, ma ho rimosso il cavo dal mio router. Sono stati tutti rilevati correttamente offline.
nycynik

3
navigator.onLine è supportato su tutti i principali browser (e lo è da tempo): caniuse.com/#feat=online-status
Rafael Lüder

@ RafaelLüder Corretto a partire da oggi, ma questa risposta è stata scritta nel gennaio 2011!
Rebecca

34

I principali fornitori di browser differiscono sul significato di "offline".

Chrome e Safari rileveranno automaticamente quando vai "offline", il che significa che gli eventi e le proprietà "online" si attivano automaticamente quando scolleghi il cavo di rete.

Firefox (Mozilla), Opera e IE adottano un approccio diverso e ti considerano "online" a meno che tu non scelga esplicitamente "Modalità offline" nel browser, anche se non hai una connessione di rete funzionante.

Ci sono argomenti validi per il comportamento di Firefox / Mozilla, che sono delineati nei commenti di questa segnalazione di bug:

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

Ma, per rispondere alla domanda, non puoi fare affidamento sugli eventi / proprietà online / offline per rilevare se esiste effettivamente una connettività di rete.

Invece, è necessario utilizzare approcci alternativi.

La sezione "Note" di questo articolo per sviluppatori Mozilla fornisce collegamenti a due metodi alternativi:

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

"Se l'API non è implementata nel browser, puoi utilizzare altri segnali per rilevare se sei offline, incluso l'ascolto di eventi di errore di AppCache e risposte da XMLHttpRequest"

Questo collega a un esempio dell'approccio "ascolto di eventi di errore di AppCache":

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

... e un esempio dell'approccio "ascolto di errori XMLHttpRequest":

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

HTH, - Ciad


1
A partire da Firefox 41: updates this property when the OS reports a change in network connectivity on Windows, Linux, and OS X.(secondo i documenti che hai menzionato). Quindi non è solo offline se stai navigando con il browser "Modalità offline"
amico

17

Oggi c'è una libreria JavaScript open source che fa questo lavoro: si chiama Offline.js.

Visualizza automaticamente le indicazioni online / offline per i tuoi utenti.

https://github.com/HubSpot/offline

Assicurati di controllare l'intero README . Contiene eventi a cui puoi collegarti.

Ecco una pagina di prova . È bellissimo / ha una bella interfaccia utente di feedback tra l'altro! :)

Offline.js Simulate UI è un plug-in Offline.js che consente di testare come le tue pagine rispondono a diversi stati di connettività senza dover utilizzare metodi di forza bruta per disabilitare la tua connettività effettiva.


2
La libreria funziona effettivamente recuperando la favicon locale ripetutamente sotto il cofano. Secondo me, la libreria è troppo "grande" e ha troppe funzionalità; il trucco principale è semplicemente recuperare ripetutamente favicon.
Karel Bílek

1
Non rileva in linea quando si scollega il cavo di rete
più elegante

15

Il modo migliore che ora funziona su tutti i principali browser è il seguente 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;
    }
})();

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


3
Come affermano chiaramente i commenti nel codice stesso , non funziona in Firefox / Chrome se si scollega il cavo Ethernet o si spegne il wifi.
Manish

Ho provato a visitare il collegamento "Sorgente" e il cavo ethernet scollegato, ha mostrato "Sei offline" in IE, ma non in Firefox / Chrome per me (utilizzando l'ultima versione di tutti i browser). Forse mi sto perdendo qualcosa?
Manish

13

Da poco tempo, navigator.onLinemostra lo stesso su tutti i principali browser ed è quindi utilizzabile.

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

Le versioni più vecchie che lo supportano nel modo giusto sono: Firefox 41 , IE 9, Chrome 14 e Safari 5.

Attualmente questo rappresenterà quasi l'intero spettro di utenti, ma dovresti sempre controllare quali funzionalità hanno gli utenti della tua pagina.

Prima di FF 41, veniva visualizzato solo falsese l'utente metteva manualmente il browser in modalità offline. In IE 8, la proprietà era su body, invece diwindow .

fonte: caniuse


11

L' window.navigator.onLineattributo e gli eventi associati sono attualmente inaffidabili su alcuni browser Web (in particolare il desktop Firefox ) come ha detto @Junto, quindi ho scritto una piccola funzione (usando jQuery) che controlla periodicamente lo stato della connettività di rete e solleva l' evento appropriato offlinee online:

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

Puoi usarlo in questo modo:

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

Per ascoltare gli eventi offline e online (con l'aiuto di jQuery):

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

7

navigator.onLine è un casino

Affronto questo quando provo a fare una chiamata ajax al server.

Esistono diverse situazioni possibili in cui il client è offline:

  • la chiamata ajax va in timeout e ricevi un errore
  • la chiamata ajax restituisce successo, ma il messaggio è nullo
  • la chiamata ajax non viene eseguita perché il browser lo decide (potrebbe essere quando navigator.onLine diventa falso dopo un po ')

La soluzione che sto usando è controllare io stesso lo stato con javascript. Ho impostato la condizione per una chiamata riuscita, in ogni altro caso presumo che il client sia offline. Qualcosa come questo:

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

5

In HTML5 puoi usare la navigator.onLineproprietà. Guarda qui:

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

Probabilmente il tuo comportamento attuale è casuale poiché il javascript prepara solo la variabile "browser" e quindi sa se sei offline e online, ma in realtà non controlla la connessione di rete.

Facci sapere se questo è quello che stai cercando.

Cordiali saluti,


Grazie per il tuo aiuto Trefex. Ho cambiato il mio codice e ora controllo solo la proprietà navigator.onLine, tuttavia ottengo lo stesso comportamento di prima. Dai un'occhiata al commento di mattbasta.
Pierre Duplouy

Ciao Pedro, sono d'accordo con mattbasta ma speravo che funzionasse per te :) Userei sicuramente il metodo Ajax per interrogare alcuni URL che sai essere sempre attivi e quindi sapresti se una connessione è persa o meno. In un'altra nota, perché è necessario il rilevamento accurato dello stato online / offline? Forse se ne sapessimo di più, ci sarebbe un'altra soluzione per il tuo problema. Fateci sapere,
Trefex

1
Ok, grazie :) Ho solo pensato che sarebbe stato meglio per l'utente se l'applicazione fosse in grado di rilevare automaticamente un cambiamento nella connettività (non è necessario abilitare manualmente la modalità offline in FF o IE). In questo modo, quando l'applicazione va offline, utilizzerà la sua cache locale invece di interrogare il server. Ho trovato questo post di John Resig, che spiega praticamente perché non funziona: ejohn.org/blog/offline-events
Pierre Duplouy

Grazie per quel post sul blog. Relly un'analisi approfondita e dritta al punto. Penso che quello che vuoi ottenere sia meglio se interroghi qualche server (forse il tuo) e poi passi alla cache locale quando c'è x numero di timeout. Cosa ne pensi ?
Trefex

Sì, immagino che sia l'opzione migliore, dato l'attuale stato dell'arte. Spero che tutti i browser alla fine saranno in grado di rilevare da soli l'effettiva perdita di connessione: usare navigator.onLine è piuttosto semplice e non dovrebbe essere più complesso. Non credi?
Pierre Duplouy

3

Si prega di trovare il modulo require.js che ho scritto per 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;
});

Per favore leggi questo post del blog e fammi sapere cosa ne pensi. http://zen-and-art-of-programming.blogspot.com/2014/04/html-5-offline-application-development.html Contiene un esempio di codice che utilizza offline.js per rilevare quando il client è offline.


3
Nota che le risposte di solo collegamento sono scoraggiate, quindi le risposte dovrebbero essere il punto finale di una ricerca di una soluzione (rispetto a un'altra sosta di riferimenti, che tendono a diventare obsoleti nel tempo). Si prega di considerare l'aggiunta di una sinossi indipendente qui, mantenendo il collegamento come riferimento.
kleopatra

Ciao, ho pubblicato il modulo require.js insieme al collegamento di riferimento. Grazie per il suggerimento.
Srihari Sridharan

2

puoi rilevare facilmente cross-browser offline come di seguito

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

puoi sostituire yoururl.com con document.location.pathname .

Il punto cruciale della soluzione è, prova a connetterti al tuo nome di dominio, se non sei in grado di connetterti, sei offline. funziona cross browser.


dato che non vi è alcun nome URL dopo il nome di dominio, non è possibile modificare il 404
harishr

A volte no, come la home page della mia API è un 404
Ben Aubin

come conta la home page della tua API? non ho capito. perché quando colpisce il server, non c'è URL, quindi nessuna elaborazione, anche se la tua home page è 404, non importa. potrebbe essere se puoi fornire un codice di esempio, che posso provare a capire il problema che stai affermando
harishr

Non solo le mie API, ma molti siti non hanno una home page. Controlla per assicurarti che il codice di stato e i dati ricevuti siano nulli, questo è il modo migliore per assicurarti che non sia solo un normale errore prevedibile
Ben Aubin

il mio webapi non ha anche una home page, ma quanto sopra funziona ancora. ecco perché sono confuso. come è importante la home page, dato che funziona
harishr

2

Uso l'opzione FALLBACK nel manifest della cache HTML5 per verificare se la mia app html5 è online o offline da:

FALLBACK:
/online.txt /offline.txt

Nella pagina html utilizzo javascript per leggere il contenuto del file txt online / offline:

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

Quando offline, lo script leggerà il contenuto di offline.txt. In base al testo nei file è possibile rilevare se la pagina web è online o offline.


0

Ecco la mia soluzione.

Testato con IE, Opera, Chrome, FireFox, Safari, come Phonegap WebApp su IOS 8 e come Phonegap WebApp su Android 4.4.2

Questa soluzione non funziona con FireFox su localhost.

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

onlineCheck.js (percorso file: "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 (percorso file: "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 (percorso file: "root"):

<?php echo 'true'; ?> 


0

Utilizzo del corpo del documento:

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

Utilizzo dell'evento 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 );

});

Riferimento :
Corpo del documento: Evento online Evento
Javascript: Eventi online e offline

Considerazioni aggiuntive:
Per spedire in giro "la connessione di rete non è la stessa della connessione a Internet" Problema dai metodi sopra: Puoi controllare la connessione a Internet una volta con Ajax all'avvio dell'applicazione e configurare una modalità online / offline. Crea un pulsante di riconnessione per consentire all'utente di andare online. E aggiungi a ogni richiesta ajax fallita una funzione che riporta l'utente alla modalità offline.


1
Questo non funzionerà: window.addEventListener('online', updateOnlineStatus(event) );perché stai chiamando immediatamente la funzione updateOnlineStatus (). Dovrebbe esserewindow.addEventListener('online', updateOnlineStatus );
Sébastien Rosset
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.