¿Detecta que la conexión a Internet está fuera de línea?

246

¿Cómo detectar que la conexión a Internet está fuera de línea en JavaScript?

Daniel Silveira
fuente
Si puede o ya usa websockets, los websockets tienen un Evento de cierre que debe llamarse si el usuario perdió la conexión con el servidor.
Simon el

Respuestas:

135

Puede determinar que la conexión se pierde haciendo solicitudes XHR fallidas .

El enfoque estándar es volver a intentar la solicitud varias veces. Si no pasa, alerta al usuario para que verifique la conexión y falla con gracia .

Nota al margen: Poner toda la aplicación en un estado "fuera de línea" puede llevar a una gran cantidad de trabajo de manejo de estado propenso a errores ... las conexiones inalámbricas pueden ir y venir, etc. Así que su mejor opción puede ser simplemente fallar con gracia, preservar el datos y alertar al usuario .. permitiéndole eventualmente solucionar el problema de conexión si existe, y continuar usando su aplicación con una buena cantidad de perdón.

Nota al margen: puede verificar la conectividad de un sitio confiable como google, pero esto puede no ser del todo útil simplemente tratando de hacer su propia solicitud, porque si bien Google puede estar disponible, su propia aplicación puede no estarlo, y usted todavía va a tiene que manejar su propio problema de conexión. Intentar enviar un ping a Google sería una buena manera de confirmar que la conexión a Internet en sí misma no funciona, por lo que si esa información es útil para usted, entonces podría valer la pena.

Nota al margen : el envío de un Ping se podría lograr de la misma manera que haría cualquier tipo de solicitud ajax bidireccional, pero enviar un ping a google, en este caso, plantearía algunos desafíos. Primero, tendríamos los mismos problemas de dominio cruzado que normalmente se encuentran al hacer comunicaciones Ajax. Una opción es configurar un proxy del lado del servidor, en el que en realidad buscamos en pingGoogle (o en cualquier sitio), y devolvemos los resultados del ping a la aplicación. Esta es una trampa-22porque si la conexión a Internet es realmente el problema, no podremos acceder al servidor, y si el problema de conexión es solo en nuestro propio dominio, no podremos notar la diferencia. Se podrían probar otras técnicas de dominio cruzado, por ejemplo, incrustando un iframe en su página que apunte a google.com, y luego sondeando el iframe por éxito / fracaso (examine el contenido, etc.). Incrustar una imagen puede no decirnos nada realmente, porque necesitamos una respuesta útil del mecanismo de comunicación para sacar una buena conclusión sobre lo que está sucediendo. De nuevo, determinar el estado de la conexión a Internet en su conjunto puede ser más problemático de lo que vale. Tendrá que sopesar estas opciones para su aplicación específica.

keparo
fuente
84
El repetido "Sidenote" suena como Dwight Schrute diciendo "Pregunta ..." :-)
Brian Kelly
19
¿Por qué está "catch-22" en negrita?
codingbear
33
Ahora en 2012 puede consultar la variable navigator.onLine;)
João Pinto Jerónimo
13
navigator.online/offline tampoco es confiable, por las mismas razones. Ver stackoverflow.com/questions/3181080/…
Efran Cobisi
17
Es posible que desee consultar Offline.js , una biblioteca de código abierto creada para este propósito.
Adam
51

IE 8 admitirá la propiedad window.navigator.onLine .

Pero, por supuesto, eso no ayuda con otros navegadores o sistemas operativos. Predigo que otros proveedores de navegadores decidirán proporcionar esa propiedad también dada la importancia de conocer el estado en línea / fuera de línea en las aplicaciones Ajax.

Hasta que eso ocurra, ya sea XHR o un Image()o <img>solicitud pueden proporcionar algo cercano a la funcionalidad que desea.

Actualización (2014/11/16)

Los principales navegadores ahora admiten esta propiedad, pero sus resultados variarán.

Cita de la documentación de Mozilla :

En Chrome y Safari, si el navegador no puede conectarse a una red de área local (LAN) o un enrutador, está desconectado; Todas las demás condiciones vuelven true. Entonces, si bien puede suponer que el navegador está fuera de línea cuando devuelve unfalse valor, no puede suponer que un valor verdadero necesariamente significa que el navegador puede acceder a Internet. Podría estar obteniendo falsos positivos, como en los casos en que la computadora ejecuta un software de virtualización que tiene adaptadores virtuales de Ethernet que siempre están "conectados". Por lo tanto, si realmente desea determinar el estado en línea del navegador, debe desarrollar medios adicionales para verificar.

En Firefox e Internet Explorer, cambiar el navegador al modo fuera de línea envía un falsevalor. Todas las demás condiciones devuelven un truevalor.

Grant Wagner
fuente
55
navigator.onLine es parte de HTML5 (otros navegadores ya tienen versiones de desarrollo que lo proporcionan), ya está disponible en Firefox 3 hoy.
olliej
-pero desafortunadamente no está disponible en versiones anteriores de IE, que a menudo estamos obligados a admitir.
keparo
22
navigator.onLine muestra el estado del navegador y no la conexión real. Por lo tanto, puede tener su navegador configurado para estar en línea, pero en realidad fallará porque la conexión está inactiva. navigator.onLine solo será falso si el navegador está configurado para navegar sin conexión.
55
Si apago el WI-FI en mi Nexus7, la página aún dice que navigator.onLine es VERDADERO. Mal ...
walv
42

Casi todos los principales navegadores ahora admiten la window.navigator.onLinepropiedad y los eventos correspondientes onliney de offlineventana:

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

Intente configurar su sistema o navegador en modo fuera de línea / en línea y verifique la consola o la window.navigator.onLinepropiedad para ver los cambios de valor. También puede probarlo en este sitio web .

Sin embargo, tenga en cuenta esta cita de la documentación de Mozilla :

En Chrome y Safari, si el navegador no puede conectarse a una red de área local (LAN) o un enrutador, está desconectado; Todas las demás condiciones vuelven true. Entonces, si bien puede suponer que el navegador está fuera de línea cuando devuelve un falsevalor , no puede suponer que un truevalor necesariamente significa que el navegador puede acceder a Internet . Podría estar recibiendo falsos positivos, como en los casos en que la computadora ejecuta un software de virtualización que tiene adaptadores virtuales de Ethernet que siempre están "conectados". Por lo tanto, si realmente desea determinar el estado en línea del navegador, debe desarrollar medios adicionales para verificar.

En Firefox e Internet Explorer, cambiar el navegador al modo fuera de línea envía un falsevalor. Hasta Firefox 41, todas las demás condiciones devuelven un truevalor; desde Firefox 41, en OS X y Windows, el valor seguirá la conectividad de red real.

(el énfasis es mío)

Esto significa que si window.navigator.onLinees así false(o si obtiene un offlineevento), se garantiza que no tendrá conexión a Internet.

trueSin embargo, si es así (o si obtiene un onlineevento), solo significa que el sistema está conectado a alguna red, en el mejor de los casos. No significa que tenga acceso a Internet, por ejemplo. Para verificar eso, aún necesitará usar una de las soluciones descritas en las otras respuestas.

Inicialmente tenía la intención de publicar esto como una actualización de la respuesta de Grant Wagner , pero parecía demasiado editado, especialmente teniendo en cuenta que la actualización de 2014 ya no era de él .

Didier L
fuente
La mejor respuesta. Gracias.
vibs2006
1
Recientemente tuve la oportunidad de trabajar un poco en el comportamiento fuera de línea. Los eventos son geniales de usar, PERO ios safari creará problemas. Cuando apaga Internet en su teléfono, los eventos fuera de línea / en línea se retrasarán hasta 2 segundos y eso puede ser problemático por razones de representación visual, ya que no puede predecir el futuro. Eso es algo que quería mencionar y que podría ayudar a alguien.
TeeJaay
38

Hay muchas maneras de hacer esto:

  • Solicitud de AJAX a su propio sitio web. Si esa solicitud falla, hay una buena posibilidad de que sea la conexión la que falla. La documentación de JQuery tiene una sección sobre el manejo de solicitudes AJAX fallidas . Tenga cuidado con la Política del mismo origen al hacer esto, que puede impedir que acceda a sitios fuera de su dominio.
  • Podrías poner onerrorun img, como

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

    Este método también podría fallar si la imagen de origen se mueve / cambia de nombre, y generalmente sería una opción inferior a la opción ajax.

Por lo tanto, hay varias formas diferentes de intentar detectar esto, ninguna perfecta, pero en ausencia de la capacidad de saltar del entorno limitado del navegador y acceder directamente al estado de conexión de red del usuario, parecen ser las mejores opciones.

ConroyP
fuente
36
 if(navigator.onLine){
  alert('online');
 } else {
  alert('offline');
 }
Edmhs
fuente
11
Siempre devuelve VERDADERO si está en el navegador.
Slavcho
2
Bueno, primero estaba tratando de desactivar SOLO LAN, pero siempre volvía VERDADERO. Entonces, cuando deshabilité todas las redes (LAN2, Virtual Box, etc.), devolvió FALSE.
Slavcho
3
Esta respuesta duplica varias respuestas existentes de 3 años antes.
JasonMArcher
2
no está comprobando la conectividad de Internet, solo está comprobando la conectividad LAN solo
Suganth G
Me funcionó en HTML 5, JavaScript, en Mac Book (usando wifi) incluso funcionó en dispositivos móviles. pero el problema es que cuando wifi está activado, devuelve VERDADERO cada vez que apago el wifi y viceversa.
S.Yadav
11

La API de caché de aplicaciones HTML5 especifica navigator.onLine, que actualmente está disponible en las versiones beta de IE8, WebKit (por ejemplo, Safari), y ya es compatible con Firefox 3

olliej
fuente
11

Puede usar la devolución de llamada de $ .ajax ()error , que se activa si la solicitud falla. Si textStatuses igual a la cadena "tiempo de espera", probablemente significa que la conexión está interrumpida:

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

Del documento :

Error : se llamará a una función si la solicitud falla. A la función se le pasan tres argumentos: el objeto XMLHttpRequest, una cadena que describe el tipo de error que se produjo y un objeto de excepción opcional, si se produjo uno. Los valores posibles para el segundo argumento (además de nulo) son "timeout", "error", "notmodified" y "parsererror". Este es un evento Ajax

Así por ejemplo:

 $.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
fuente
9

Como dijo olliej, navigator.onLinees preferible usar la propiedad del navegador que enviar solicitudes de red y, en consecuencia, con developer.mozilla.org/En/Online_and_offline_events , incluso es compatible con versiones antiguas de Firefox e IE.

Recientemente, el WHATWG ha especificado la adición de los eventos onliney offline, en caso de que necesite reaccionar antenavigator.onLine cambios.

También preste atención al enlace publicado por Daniel Silveira que señala que confiar en esas señales / propiedades para sincronizar con el servidor no siempre es una buena idea.


fuente
ACTUALIZACIÓN: a partir de 2015 parece estar funcionando en la mayoría de los navegadores, consulte el gráfico y el artículo de
Olga
8
window.navigator.onLine

es lo que está buscando, pero aquí hay algunas cosas que agregar, primero, si es algo en su aplicación que desea seguir verificando (como ver si el usuario se desconecta repentinamente, lo cual es correcto en este caso la mayor parte del tiempo, luego usted necesita escuchar el cambio también), para eso agrega un escucha de eventos a la ventana para detectar cualquier cambio, para verificar si el usuario se desconecta, puede hacer:

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

y para verificar si está en línea:

window.addEventListener("online", 
  ()=> console.log("Connected Internet")
);
Alireza
fuente
2
Tienes que tener cuidado con onLine. Los navegadores definen el estado de estar en línea de manera muy diferente. Echa un vistazo a developer.mozilla.org/en-US/docs/Web/API/NavigatorOnLine/onLine .
Andreas Baumgart
1
Tu respuesta es incorrecta. La propiedad 'onLine' no tiene nada que ver con la conectividad a internet. Consulte la referencia anterior sobre la API web.
Alexandre V.
7

Tuve que hacer una aplicación web (basada en ajax) para un cliente que trabaja mucho con las escuelas, estas escuelas a menudo tienen una mala conexión a Internet. ¡Utilizo esta función simple para detectar si hay una conexión, funciona muy bien!

Yo uso CodeIgniter y 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
fuente
6

Una llamada ajax a su dominio es la forma más fácil de detectar si está desconectado

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

esto es solo para darle el concepto, debería mejorarse.

Por ejemplo, error = 404 aún debería significar que estás en línea

harishr
fuente
4

Creo que es una forma muy simple.

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
fuente
onLine no significa que haya una conexión a internet. De acuerdo con 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
Shmuel Kamensky
2

Estaba buscando una solución del lado del cliente para detectar si Internet estaba caído o si mi servidor estaba caído. Las otras soluciones que encontré siempre parecían depender de un archivo o imagen de script de un tercero, lo que para mí no parecía resistir el paso del tiempo. Una imagen o script alojado externo podría cambiar en el futuro y provocar un error en el código de detección.

He encontrado una manera de detectarlo buscando un xhrStatus con un código 404. Además, uso JSONP para evitar la restricción CORS. Un código de estado que no sea 404 muestra que la conexión a Internet no funciona.

$.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)
        }
    }
});
camino del futuro
fuente
2
Eso no funciona a partir del 10-5-2016, no estoy seguro de por qué simplemente no quiero que se desperdicie el tiempo de otras personas.
Bren
No creo que funcione para errores de solicitud prohibidos y malos :)
Faisal Naseer
1

Mi manera.

<!-- 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>
no sujeto
fuente
1

El problema de algunos métodos navigator.onLinees que no son compatibles con algunos navegadores y versiones móviles, una opción que me ayudó mucho fue usar el XMLHttpRequestmétodo clásico y también prever el posible caso de que el archivo se almacenara en caché con respuestaXMLHttpRequest.status mayor que 200 y menos de 304.

Aquí está mi código:

 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
fuente
0

Hay dos respuestas para dos senarios diferentes:

  1. Si está utilizando JavaScript en un sitio web (es decir, o en cualquier parte frontal) La forma más sencilla de hacerlo es:

    <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. Pero si está utilizando js en el lado del servidor (es decir, nodo, etc.), puede determinar que la conexión se pierde al realizar solicitudes XHR fallidas.

    El enfoque estándar es volver a intentar la solicitud varias veces. Si no pasa, alerta al usuario para que verifique la conexión y falla con gracia.

Rishabh Anand
fuente
0

cabeza de solicitud en error de solicitud

$.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
fuente
-1

Aquí hay un fragmento de una utilidad auxiliar que tengo. Este es JavaScript de espacio de nombres:

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

Debería usar esto con la detección de métodos; de lo contrario, active una forma 'alternativa' de hacerlo. Se acerca rápidamente el momento en que esto será todo lo que se necesita. Los otros métodos son hacks.

Peter Mortensen
fuente