En una callback de $ .ajax, ¿cómo distingo un servidor inalcanzable de un usuario que se aleja?

Situación:

Tienes algunas solicitudes de $ .ajax para el servidor que aún se están ejecutando. Todos ellos cometieron errores con xhr.status === 0 y xhr.readyState === 0.

Posibles causas:

  • El servidor está inactivo (EDIT: como en inalcanzable: no se devuelven encabezados ni nada).
  • El usuario hizo clic en un enlace / actualizó la página / de lo contrario navegó.

Me gustaría abrir un diálogo en el primer caso, pero ignorar el segundo. ¿Cómo distingo entre estos dos en mi método completo? El método completo se activa antes del evento $ (window) .unload, por lo que no puedo usarlo para determinar si el usuario hizo clic. También podría usar un setTimeout para tratar de esperar a que se cargue la siguiente página, pero eso está sucio. ¿Hay algo más que pueda hacer?

(Esta respuesta es un resumen de otra respuesta, en aras de la claridad por solicitud del OP)
Si un indicador de nivel de ventana no funciona, el siguiente evento de nivel dom para probar antes de $(window).unload es window.onbeforeunload $(window).unload . ¿Es esa una opción viable?

Alrededor de su método AJAX:

 var running = true; // do this only once!!! var _obunload = ( window.onbeforeunload )? window.onbeforeunload: function(){}; window.onbeforeunload = function() { _obunload.call( window ); running = false; } xhr.onreadystatechange = function() { if( !xhr.status && !xhr.readyState && running ) { // warning! warning! danger Will Robinson! // there was a server error } else if( !xhr.status && !xhr.readyState ) { // user did something... Who gives? } running = false; } 

Puede verificar una respuesta de tiempo de espera desde el servidor:

 timeout:500, error: function(jqXHR, textStatus, errorThrown) { if(textStatus==="timeout") { alert("got timeout"); } else { // Some other error } } 

idea 3

Bueno, siempre existe la posibilidad de simular un retraso desde el servidor inexistente:

 var running = true; xhr.onreadystatechange = function() { if( !xhr.status && !xhr.readyState ) { // wait a short while to see whether the page is unloading. setTimeout( unloadTest, 250 ); } else { running = false; } } function unloadTest() { // running will be set to false by onbeforeunload, which means this // should only be true if there was some form of server error. if( running ) // Regnad? Robin Williams? } 

Luego, en otra parte:

 // (using generic JS, you can use $(window).bind( 'beforeunload' ... window.onbeforeunload = function() { running = false; } 

idea 2

Bueno, si a continuación no funciona, el siguiente evento de nivel dom para probar antes de $(window).unload es window.onbeforeunload . ¿Es esa una opción viable?

Alrededor de su método AJAX:

 var running = true; xhr.onreadystatechange = function() { if( !xhr.status && !xhr.readyState && running ) { // warning! warning! danger Will Robinson! // there was a server error } else if( !xhr.status && !xhr.readyState ) { // user did something... Who gives? } running = false; } 

Luego, en otra parte:

 // (using generic JS, you can use $(window).bind( 'beforeunload' ... window.onbeforeunload = function() { running = false; } 

Post original (aparentemente no esta funcionando)

¿Por qué no establecer una bandera en la propia ventana?

    

Entonces, cuando estás a punto de llamar $.ajax :

 // winTime is bound to window.currentTime at the time of the original query. var winTime = window.currentTime; // using onreadystatechange because it looks like you're looking for that in your // question. This can be easily adapted to $.ajax, however. xhr.onreadystatechange = function() { if( !xhr.status && !xhr.readyState && winTime == window.currentTime ) { // warning! warning! danger Will Robinson! // there was a server error } else if( !xhr.status && !xhr.readyState ) { // user did something... Who gives? } }