Wykryć, że połączenie internetowe jest offline?

246

Jak wykryć połączenie internetowe w JavaScript w trybie offline?

Daniel Silveira
źródło
Jeśli możesz lub już używasz websockets - websockets mają zdarzenie Close, które musi zostać wywołane, jeśli użytkownik utracił połączenie z serwerem.
Simon

Odpowiedzi:

135

Możesz ustalić, że połączenie zostało utracone, wykonując nieudane żądania XHR .

Standardowym podejściem jest ponowienie próby kilka razy. Jeśli nie przejdzie, powiadom użytkownika, aby sprawdził połączenie i z wdziękiem się nie powiedzie .

Sidenote: Ustawienie całej aplikacji w trybie „offline” może prowadzić do wielu podatnych na błędy prac związanych z obsługą stanu. Połączenia bezprzewodowe mogą przychodzić i odchodzić itp. Dlatego najlepszym rozwiązaniem może być po prostu wdzięczne niepowodzenie, zachowanie dane i powiadom użytkownika, pozwalając mu ostatecznie rozwiązać problem z połączeniem, jeśli taki istnieje, i kontynuować korzystanie z aplikacji z dużą dozą przebaczenia.

Sidenote: Możesz sprawdzić wiarygodną witrynę, taką jak Google, pod kątem łączności, ale może to nie być całkiem przydatne, jak próba złożenia własnego żądania, ponieważ chociaż Google może być dostępny, Twoja aplikacja może nie być, a nadal będziesz poradzić sobie z własnym problemem z połączeniem Próba wysłania polecenia ping do Google byłaby dobrym sposobem na potwierdzenie, że samo połączenie internetowe jest niedostępne, więc jeśli ta informacja jest dla Ciebie przydatna, być może warto.

Sidenote : Wysłanie Pinga można osiągnąć w taki sam sposób, jak w przypadku dowolnego dwukierunkowego żądania ajax, ale w tym przypadku wysłanie pinga do Google stanowiłoby pewne wyzwanie. Po pierwsze, mielibyśmy te same problemy między domenami, które zwykle występują przy tworzeniu komunikacji Ajax. Jedną z opcji jest skonfigurowanie serwera proxy po stronie serwera, w którym faktycznie pinggoogle (lub jakakolwiek inna strona) i zwracamy wyniki ping do aplikacji. To jest catch-22ponieważ jeśli połączenie internetowe stanowi problem, nie będziemy w stanie uzyskać dostępu do serwera, a jeśli problem z połączeniem dotyczy tylko naszej własnej domeny, nie będziemy w stanie stwierdzić różnicy. Można wypróbować inne techniki między domenami, na przykład osadzenie iframe na stronie, która wskazuje na google.com, a następnie sondowanie iframe pod kątem sukcesu / niepowodzenia (sprawdź zawartość itp.). Osadzanie obrazu może nam niewiele powiedzieć, ponieważ potrzebujemy użytecznej odpowiedzi od mechanizmu komunikacji, aby wyciągnąć dobre wnioski na temat tego, co się dzieje. Zatem ponownie określenie stanu połączenia internetowego jako całości może być większym problemem niż jest to warte. Będziesz musiał rozważyć te opcje dla konkretnej aplikacji.

keparo
źródło
84
Powtarzające się „Sidenote” brzmi jak Dwight Schrute, mówiąc „Pytanie ...” :-)
Brian Kelly
19
Dlaczego „catch-22” jest pogrubiony?
codingbear
33
Teraz w 2012 roku możesz sprawdzić zmienną navigator.onLine;)
João Pinto Jerónimo
13
navigator.online/offline jest również zawodny, z tych samych powodów. Zobacz stackoverflow.com/questions/3181080/…
Efran Cobisi,
17
Możesz sprawdzić Offline.js , bibliotekę typu open source zbudowaną właśnie do tego celu.
Adam
51

IE 8 będzie obsługiwał window.navigator.onLine właściwość .

Ale to oczywiście nie pomaga w przypadku innych przeglądarek lub systemów operacyjnych. Przewiduję, że inni dostawcy przeglądarek również zdecydują się na udostępnienie tej właściwości, biorąc pod uwagę znaczenie znajomości statusu online / offline w aplikacjach Ajax.

Dopóki to nie nastąpi, albo XHR lub Image()lub<img> żądanie może zapewnić coś zbliżonego do pożądanej funkcjonalności.

Aktualizacja (2014/11/16)

Duże przeglądarki obsługują teraz tę właściwość, ale wyniki będą się różnić.

Cytat z dokumentacji Mozilli :

W przeglądarce Chrome i Safari, jeśli przeglądarka nie może połączyć się z siecią lokalną (LAN) lub routerem, jest offline; wszystkie pozostałe warunki powracają true. Chociaż można założyć, że przeglądarka jest offline, gdy zwraca falsewartość, nie można założyć, że prawdziwa wartość musi koniecznie oznaczać, że przeglądarka może uzyskać dostęp do Internetu. Możliwe, że otrzymujesz fałszywe alarmy, na przykład w przypadku, gdy na komputerze jest uruchomione oprogramowanie do wirtualizacji z wirtualnymi adapterami Ethernet, które są zawsze „połączone”. Dlatego jeśli naprawdę chcesz ustalić status online przeglądarki, powinieneś opracować dodatkowe sposoby sprawdzania.

W Firefox i Internet Explorer przełączenie przeglądarki do trybu offline powoduje wysłanie falsewartości. Wszystkie pozostałe warunki zwracają truewartość.

Grant Wagner
źródło
5
navigator.onLine jest częścią HTML5 - inne przeglądarki mają już wersje programistyczne, które to zapewniają - jest już dostępne w Firefox 3 już dziś.
olliej
-Ale niestety nie jest dostępny we wcześniejszych wersjach IE, które często musimy obsługiwać.
keparo,
22
navigator.onLine pokazuje stan przeglądarki, a nie faktyczne połączenie. Możesz więc ustawić swoją przeglądarkę jako onLine, ale tak naprawdę to się nie powiedzie, ponieważ połączenie nie działa. navigator.onLine będzie fałszywe tylko wtedy, gdy przeglądarka jest ustawiona na przeglądanie offline.
5
jeśli wyłączę Wi-Fi na moim Nexusie 7, strona nadal będzie mówić, że navigator.onLine ma wartość TRUE. Zły ...
walv
42

Prawie wszystkie główne przeglądarki obsługują teraz tę window.navigator.onLinewłaściwość, a odpowiednie zdarzenia okna onlinei offline:

window.addEventListener('online', () => console.log('came online'));
window.addEventListener('offline', () => console.log('came offline'));

Spróbuj ustawić system lub przeglądarkę w trybie offline / online i sprawdź konsolę lub window.navigator.onLinewłaściwość pod kątem zmian wartości. Możesz to również przetestować na tej stronie .

Zwróć jednak uwagę na ten cytat z Dokumentacji Mozilli :

W przeglądarce Chrome i Safari, jeśli przeglądarka nie może połączyć się z siecią lokalną (LAN) lub routerem, jest offline; wszystkie pozostałe warunki powracają true. Chociaż można założyć, że przeglądarka jest w trybie offline, gdy zwraca falsewartość , nie można założyć, że truewartość koniecznie oznacza, że ​​przeglądarka może uzyskać dostęp do Internetu . Możliwe, że otrzymujesz fałszywe alarmy, na przykład w przypadku, gdy na komputerze jest uruchomione oprogramowanie do wirtualizacji z wirtualnymi adapterami Ethernet, które są zawsze „połączone”. Dlatego jeśli naprawdę chcesz ustalić status online przeglądarki, powinieneś opracować dodatkowe sposoby sprawdzania.

W Firefox i Internet Explorer przełączenie przeglądarki do trybu offline powoduje wysłanie falsewartości. Do Firefoksa 41 wszystkie pozostałe warunki zwracają truewartość; od przeglądarki Firefox 41 w systemach OS X i Windows wartość będzie odpowiadać rzeczywistej łączności sieciowej.

(nacisk jest mój)

Oznacza to, że jeśli window.navigator.onLinejest false(lub dostaniesz offlinezdarzenie), masz gwarancję, że nie masz połączenia z Internetem.

Jeśli tak jest true(lub dostaniesz onlinezdarzenie), oznacza to, że system jest w najlepszym razie podłączony do jakiejś sieci. Nie oznacza to na przykład, że masz dostęp do Internetu. Aby to sprawdzić, nadal będziesz musiał skorzystać z jednego z rozwiązań opisanych w innych odpowiedziach.

Początkowo zamierzałem opublikować to jako aktualizację odpowiedzi Granta Wagnera , ale wydawało się to zbyt dużą edycją, zwłaszcza biorąc pod uwagę, że aktualizacja 2014 nie była już od niego .

Didier L.
źródło
Najlepsza odpowiedź. Dzięki.
vibs2006
1
Niedawno miałem okazję popracować trochę nad zachowaniem offline. Wydarzenia są świetne w użyciu, ALE safari ios spowoduje problemy. Gdy włączysz internet w telefonie, wydarzenia offline / online zostaną opóźnione o maksymalnie 2 sekundy, co może być problematyczne z powodu renderowania wizualnego, ponieważ nie możesz przewidzieć przyszłości. To tylko coś, o czym chciałem wspomnieć i może komuś pomóc.
TeeJaay
38

Można to zrobić na kilka sposobów:

  • Żądanie AJAX na własną stronę internetową. Jeśli to żądanie nie powiedzie się, istnieje duże prawdopodobieństwo, że to połączenie jest wadliwe. Dokumentacja JQuery zawiera sekcję dotyczącą obsługi nieudanych żądań AJAX . Przestrzegaj przy tym tych samych zasad pochodzenia , które mogą uniemożliwić ci dostęp do stron spoza Twojej domeny.
  • Możesz umieścić onerrorw img, jak

    <img src='http://www.example.com/singlepixel.gif' 
          onerror='alert("Connection dead");' />

    Ta metoda mogłaby również zawieść, jeśli obraz źródłowy został przeniesiony / zmieniono jego nazwę, i ogólnie byłby gorszym wyborem niż opcja ajax.

Istnieje więc kilka różnych sposobów na wykrycie tego, żaden z nich nie jest idealny, ale przy braku możliwości wyskoczenia z piaskownicy przeglądarki i uzyskania bezpośredniego dostępu do stanu połączenia sieciowego użytkownika, wydają się być najlepszymi opcjami.

ConroyP
źródło
36
 if(navigator.onLine){
  alert('online');
 } else {
  alert('offline');
 }
Edmhs
źródło
11
Zwraca zawsze PRAWDA, jeśli w przeglądarce.
Slavcho
2
Cóż, najpierw próbowałem wyłączyć TYLKO LAN, ale zawsze zwracało PRAWDA. Więc kiedy wyłączyłem wszystkie sieci (LAN2, Virtual Box itp.), Zwrócił FALSE.
Slavcho
3
Ta odpowiedź powiela kilka istniejących odpowiedzi sprzed 3 lat.
JasonMArcher
2
nie sprawdza łączności z Internetem, sprawdza tylko samą łączność LAN
Suganth G
Pracował dla mnie w HTML 5, JavaScript, w książce Mac (za pomocą Wi-Fi) nawet pracował na urządzeniach mobilnych. ale problem polega na tym, że gdy Wi-Fi na nim zwraca PRAWDA za każdym razem, nawet ja wyłączam Wi-Fi na odwrót.
S.Yadav,
11

Interfejs API pamięci podręcznej aplikacji HTML5 określa navigator.onLine, który jest obecnie dostępny w wersjach beta IE8, nightlies WebKit (np. Safari) i jest już obsługiwany w Firefox 3

olliej
źródło
11

Można użyć $ .ajax () „s errorzwrotna, która pożary, jeżeli żądanie nie powiedzie się. Jeśli textStatusjest równy ciągowi „limit czasu”, prawdopodobnie oznacza to, że połączenie zostało zerwane:

function (XMLHttpRequest, textStatus, errorThrown) {
  // typically only one of textStatus or errorThrown 
  // will have info
  this; // the options for this ajax request
}

Z dokumentu :

Błąd : funkcja, która ma zostać wywołana, jeśli żądanie nie powiedzie się. Do funkcji przekazywane są trzy argumenty: obiekt XMLHttpRequest, ciąg znaków opisujący typ błędu, który wystąpił, oraz opcjonalny obiekt wyjątku, jeśli taki wystąpił. Możliwe wartości dla drugiego argumentu (oprócz null) to „limit czasu”, „błąd”, „niezmodyfikowany” i „parsererror”. To jest wydarzenie Ajax

Na przykład:

 $.ajax({
   type: "GET",
   url: "keepalive.php",
   success: function(msg){
     alert("Connection active!")
   },
   error: function(XMLHttpRequest, textStatus, errorThrown) {
       if(textStatus == 'timeout') {
           alert('Connection seems dead!');
       }
   }
 });
karim79
źródło
9

Jak powiedział olliej, korzystanie z navigator.onLinewłaściwości przeglądarki jest lepsze niż wysyłanie żądań sieciowych i, zgodnie z developer.mozilla.org/En/Online_and_offline_events , jest nawet obsługiwane przez starsze wersje Firefox i IE.

Ostatnio WHATWG określiło dodanie zdarzeń onlinei offline, na wypadek, gdybyś musiał zareagować na navigator.onLinezmiany.

Proszę również zwrócić uwagę na link opublikowany przez Daniela Silveirę, który wskazuje, że poleganie na tych sygnałach / właściwościach do synchronizacji z serwerem nie zawsze jest dobrym pomysłem.


źródło
AKTUALIZACJA: Począwszy od 2015 r. Wydaje się działać w większości przeglądarek, zobacz wykres kajakowy i artykuł
Olga
8
window.navigator.onLine

to jest to, czego szukasz, ale tutaj jest kilka rzeczy, które należy dodać, jeśli chcesz coś sprawdzić w swojej aplikacji (na przykład sprawdzić, czy użytkownik nagle przejdzie w tryb offline, co w tym przypadku jest poprawne przez większość czasu) trzeba także posłuchać zmiany), aby dodać detektor zdarzeń do okna w celu wykrycia każdej zmiany, aby sprawdzić, czy użytkownik przejdzie w tryb offline, możesz:

window.addEventListener("offline", 
  ()=> console.log("No Internet")
);

i do sprawdzenia, czy online:

window.addEventListener("online", 
  ()=> console.log("Connected Internet")
);
Alireza
źródło
2
Musisz być ostrożny onLine. Przeglądarki definiują stan bycia online bardzo różnie. Zajrzyj na developer.mozilla.org/en-US/docs/Web/API/NavigatorOnLine/onLine .
Andreas Baumgart
1
Twoja odpowiedź jest zła. Właściwość „onLine” nie ma nic wspólnego z łącznością internetową. Zobacz powyższe odniesienie do interfejsu API.
Alexandre V.
7

Musiałem stworzyć aplikację internetową (opartą na ajax) dla klienta, który dużo współpracuje ze szkołami, szkoły te często mają złe połączenie internetowe. Używam tej prostej funkcji do wykrycia, czy istnieje połączenie, działa bardzo dobrze!

Używam CodeIgniter i Jquery:

function checkOnline() {
    setTimeout("doOnlineCheck()", 20000);
}

function doOnlineCheck() {
    //if the server can be reached it returns 1, other wise it times out
    var submitURL = $("#base_path").val() + "index.php/menu/online";

    $.ajax({
        url : submitURL,
        type : "post",
        dataType : "msg",
        timeout : 5000,
        success : function(msg) {
            if(msg==1) {
                $("#online").addClass("online");
                $("#online").removeClass("offline");
            } else {
                $("#online").addClass("offline");
                $("#online").removeClass("online");
            }
            checkOnline();
        },
        error : function() {
            $("#online").addClass("offline");
            $("#online").removeClass("online");
            checkOnline();
        }
    });
}
THEO
źródło
6

wywołanie ajax do Twojej domeny jest najprostszym sposobem na wykrycie, czy jesteś offline

$.ajax({
      type: "HEAD",
      url: document.location.pathname + "?param=" + new Date(),
      error: function() { return false; },
      success: function() { return true; }
   });

tylko po to, aby dać ci koncepcję, należy ją ulepszyć.

Np. Błąd = 404 powinien nadal oznaczać, że jesteś online

harishr
źródło
4

Myślę, że to bardzo prosty sposób.

var x = confirm("Are you sure you want to submit?");
if (x) {
  if (navigator.onLine == true) {
    return true;
  }
  alert('Internet connection is lost');
  return false;
}
return false;
Prakash Pazhanisamy
źródło
OnLine nie oznacza, że ​​istnieje połączenie z Internetem. Według developer.mozilla.org/en-US/docs/Web/API/NavigatorOnLine/onLine if the browser is not able to connect to a local area network (LAN) or a router, it is offline; all other conditions return true
Szmula Kamenský
2

Szukałem rozwiązania po stronie klienta, aby wykryć, czy Internet nie działa lub czy mój serwer nie działa. Inne rozwiązania, które zawsze znajdowałem, wydawały się zależeć od pliku skryptu lub obrazu innej firmy, co nie wydawało mi się, żeby wytrzymało próbę czasu. Zewnętrzny hostowany skrypt lub obraz może w przyszłości ulec zmianie i spowodować awarię kodu wykrywającego.

Znalazłem sposób, aby to wykryć, szukając xhrStatus z kodem 404. Ponadto używam JSONP do ominięcia ograniczenia CORS. Kod stanu inny niż 404 pokazuje, że połączenie internetowe nie działa.

$.ajax({
    url:      'https://www.bing.com/aJyfYidjSlA' + new Date().getTime() + '.html',
    dataType: 'jsonp',
    timeout:  5000,

    error: function(xhr) {
        if (xhr.status == 404) {
            //internet connection working
        }
        else {
            //internet is down (xhr.status == 0)
        }
    }
});
sposób na przyszłość
źródło
2
To nie działa na dzień 10-5-2016. Nie jestem pewien, dlaczego po prostu nie chcemy tracić czasu innych ludzi.
Bren,
Nie sądzę, więc to zadziała dla zabronionych i błędnych błędów żądania :)
Faisal Naseer
1

Moja droga.

<!-- the file named "tt.jpg" should exist in the same directory -->

<script>
function testConnection(callBack)
{
    document.getElementsByTagName('body')[0].innerHTML +=
        '<img id="testImage" style="display: none;" ' +
        'src="tt.jpg?' + Math.random() + '" ' +
        'onerror="testConnectionCallback(false);" ' +
        'onload="testConnectionCallback(true);">';

    testConnectionCallback = function(result){
        callBack(result);

        var element = document.getElementById('testImage');
        element.parentNode.removeChild(element);
    }    
}
</script>

<!-- usage example -->

<script>
function myCallBack(result)
{
    alert(result);
}
</script>

<a href=# onclick=testConnection(myCallBack);>Am I online?</a>
unxed
źródło
1

Problem niektórych metod, takich jak navigator.onLineto, że nie są one kompatybilne z niektórymi przeglądarkami i wersjami mobilnymi, opcja, która bardzo mi pomogła, to użycie klasycznej XMLHttpRequestmetody, a także przewidzenie możliwego przypadku, że plik był przechowywany w pamięci podręcznej z odpowiedzią XMLHttpRequest.statuswiększą niż 200 i mniej niż 304.

Oto mój kod:

 var xhr = new XMLHttpRequest();
 //index.php is in my web
 xhr.open('HEAD', 'index.php', true);
 xhr.send();

 xhr.addEventListener("readystatechange", processRequest, false);

 function processRequest(e) {
     if (xhr.readyState == 4) {
         //If you use a cache storage manager (service worker), it is likely that the
         //index.php file will be available even without internet, so do the following validation
         if (xhr.status >= 200 && xhr.status < 304) {
             console.log('On line!');
         } else {
             console.log('Offline :(');
         }
     }
}
Vladimir Salguero
źródło
0

Istnieją dwie odpowiedzi dla dwóch różnych senariów: -

  1. Jeśli używasz JavaScript na stronie internetowej (tj; lub jakiejkolwiek części front-end) Najprostszym sposobem na to jest:

    <h2>The Navigator Object</h2>
    
    <p>The onLine property returns true if the browser is online:</p>
    
    <p id="demo"></p>
    
    <script>
      document.getElementById("demo").innerHTML = "navigator.onLine is " + navigator.onLine;
    </script>

  2. Ale jeśli używasz js po stronie serwera (tj. Węzła itp.), Możesz ustalić, że połączenie zostało zerwane przez wykonanie nieudanych żądań XHR.

    Standardowym podejściem jest ponowienie próby kilka razy. Jeśli nie przejdzie, powiadom użytkownika, aby sprawdził połączenie i z wdziękiem się nie powiedzie.

Rishabh Anand
źródło
0

błąd żądania żądania

$.ajax({
    url: /your_url,
    type: "POST or GET",
    data: your_data,
    success: function(result){
      //do stuff
    },
    error: function(xhr, status, error) {

      //detect if user is online and avoid the use of async
        $.ajax({
            type: "HEAD",
            url: document.location.pathname,
            error: function() { 
              //user is offline, do stuff
              console.log("you are offline"); 
              }
         });
    }   
});
Kareem
źródło
-1

Oto fragment narzędzia pomocniczego, które mam. To jest javascript z przestrzenią nazw:

network: function() {
    var state = navigator.onLine ? "online" : "offline";
    return state;
}

Powinieneś używać tego z wykrywaniem metod, w przeciwnym razie uruchom „alternatywny” sposób na wykonanie tego. Zbliża się czas, kiedy będzie to wszystko, czego potrzeba. Inne metody to hacki.

Peter Mortensen
źródło