2009-09-02 8 views
28

Si navego fuera de una página en medio de una solicitud $ .ajax(), se activa la devolución de llamada de error. He probado en Safari y FF con solicitudes GET y POST.jQuery AJAX activa la devolución de llamada de error en la descarga de la ventana: ¿cómo puedo filtrar la descarga y solo detectar errores reales?

Una posible solución sería abortar todas las solicitudes de AJAX en la descarga de la página, pero se llama al controlador de errores antes de descargar, por lo que esto no parece posible.

Quiero ser capaz de manejar correctamente errores REALES como 500s en el lado del cliente con una alerta cortés o un cuadro de diálogo modal, pero no quiero que se invoque este manejo cuando un usuario navega fuera de la página.

¿Cómo puedo hacer esto?

-

(también extraña: Al navegar lejos de una página, el gestor de errores dice que el parámetro textStatus es "error", el mismo se lanza al recibir un/solicitud incorrecta 500).

+2

alerta cortés - ¡Existe tal cosa! – redsquare

+0

Ahora estoy enfrentando la misma situación contigo, Graham. ¡Gracias por publicar! –

+0

https://bugzilla.mozilla.org/show_bug.cgi?id=768596 – 4esn0k

Respuesta

24

En la devolución de llamada de error o $.ajax tiene tres argumentos de entrada:

function (XMLHttpRequest, textStatus, errorThrown) { 
    this; // options for this ajax request 
} 

Usted puede comprobar directamente la xhr.status para obtener el código de respuesta HTTP, por ejemplo:

$.ajax({ 
    url: "test.html", 
    cache: false, 
    success: function(html){ 
    $("#results").append(html); 
    }, 
    error: function (xhr, textStatus) { 
    if (xhr.status == 500) { 
     alert('Server error: '+ textStatus); 
    } 
    } 
}); 

Editar: Para ver la diferencia entre una conexión interrumpida por el navegador y el caso donde el servidor está caído (comentario de jasonmerino):

En la descarga xhr.readyState debe ser 0, donde por un servidor no responde la xhr.readyState debe ser 4.

+4

Tiene sentido, al descargar el estado = 0, gracias. – Graham

+3

Estado = 0 también si el servidor no responde (está inactivo). – Mitar

+1

Dado que tiene el mismo valor de estado, ¿cómo diferenciar descargar y no responder? –

0

La devolución de llamada de error debería hacer referencia al objeto XHR, verificar el código de estado para ver si es un error del servidor o no.

4

(me gustaría añadir esto como un comentario a la respuesta principal ¡pero aún no ha acumulado suficientes puntos para hacerlo!)

También estoy viendo esto en FF4 y Chrome (9.0.597.107). Probablemente en otro lugar, pero eso es lo suficientemente malo como para querer arreglarlo.

Una de las cosas que es extraño en esta situación es que regresó XMLHttpRequest.status === 0

cual parece ser una manera confiable para detectar esta situación y, en mi caso particular, abortar el tratamiento de errores a medida que se muestra al usuario:

error: function (XMLHttpRequest, textStatus, errorThrown) { 
    if (XMLHttpRequest.status === 0) return; 
    // error handling here 
} 

también vale la pena mencionar que en el supuesto de si puede ser un problema en el análisis sintáctico JSON de lo que el navegador está dando la espalda a la llamada $ .ajax(), que también trataron el canje de la JSON.stringify nativo para la versión de Douglas Crockford (https://github.com/douglascrockford/JSON-js) pero eso no hizo diferencia.

+3

Estado = 0 también si el servidor no responde (está inactivo). – Mitar

+0

Acabo de experimentar y sí - el 0 se devuelve si el servidor HTTP (Apache en mi caso) ya está inactivo cuando se realiza la solicitud, o se termina mientras la solicitud es con el servidor de la aplicación (JBoss en mi caso) . – RedYeti

+0

Por lo que vale: Terminar el servidor de aplicaciones a mitad de solicitud (lo tuve en un punto de interrupción) me devolvió un estado 502, mientras que si el servidor de aplicaciones no se estaba ejecutando cuando hice la solicitud obtuve un 503 (el servidor HTTP estaba ejecutando ambos veces por supuesto). – RedYeti

11

Este es un dispositivo difícil de manejar correctamente en todas las situaciones. Desafortunadamente, en muchos navegadores populares, el xhr.status es el mismo (0) si la llamada AJAX se cancela mediante navegación o si un servidor está inactivo o no responde.Entonces esa técnica rara vez funciona.

Aquí hay un conjunto de hacks muy "prácticos" que he acumulado que funcionan bastante bien en la mayoría de las circunstancias, pero que aún no son a prueba de balas. La idea es tratar de atrapar los eventos de navegación y establecer una bandera que esté marcada en el controlador de error AJAX. De esta manera:

var global_is_navigating = false; 

$(window).on('beforeunload',function() { 
    // Note: this event doesn't fire in mobile safari 
    global_is_navigating = true; 
}); 

$("a").on('click',function() { 
    // Giant hack that can be helpful with mobile safari 
    if($(this).attr('href')) { 
     global_is_navigating = true; 
    } 
}); 

$(document).ajaxError(function(evt, xhr, settings) { 
    // default AJAX error handler for page 
    if(global_is_navigating) { 
     // AJAX call cancelled by navigation. Not a real error 
     return; 
    } 
    // process actual AJAX error here. 
}); 
+1

Gracias por la solución, acabo de notar un error tipográfico en el código. Al final del código, falta un paréntesis y un punto y coma. Entonces el último método se verá así. '$ (document) .ajaxError (function (evt, XHR, ajustes) {// \t predeterminado AJAX gestor de errores de la página si (global_is_navigating) {// llamada AJAX cancelado por la navegación. No es un retorno de error reales ; } }); ' –

+0

Se corrigieron los errores tipográficos, ¡gracias! – Leopd

+0

Para su información, la solución para la versión móvil de Safari sigue siendo necesaria para iOS 10 –

0

Si usted hace uso de funciones tales como jQuery $.get, $.post, $.ajax ... a continuación, puede utilizar el parámetro text_status para comprobar qué tipo de falta es:

request = $.get('test.html', function(data){ 
    //whatever 
}).fail(function(xhr, text_status, error_thrown) { 

    if(text_status!== 'abort'){ 
     console.warn("Error!!"); 
    } 
}); 

De la jQuery docs:

jqXHR.fail (function (jqXHR, textStatus, errorThrown) {}); Una construcción alternativa a la opción de devolución de llamada de error, el método .fail() reemplaza el método obsoleto .error(). Consulte deferred.fail() para detalles de implementación de .

Cuestiones relacionadas