Manejo de errores de Jquery Ajax para ignorar abortado

81

Quiero tener un método de manejo de errores global para llamadas ajax, esto es lo que tengo ahora:

$.ajaxSetup({
  error: function (XMLHttpRequest, textStatus, errorThrown) {
    displayError();
  }
});

Necesito ignorar el error de aborted. errorThrownes nulo y textStatuses error. ¿Cómo verifico aborted?

Shawn Mclean
fuente
4
Para mí, textStatus es "abortar". Veo que esta es una vieja pregunta, tal vez haya cambiado.
jackocnr
Para mí, sigue siendo un "error".
Jānis Elmeris
Sí, lamentablemente varía según el navegador.
Christophe Roussy
Ver también: github.com/angular/angular.js/issues/15924 (2017)
Christophe Roussy
1
Si llama abortde forma manual (y no estoy seguro de que cuando otro él llamará) se puede pasar en el mensaje de error: abort("abort").
MyiEye

Respuestas:

52

Tuve que lidiar con el mismo caso de uso hoy. La aplicación en la que estoy trabajando tiene estas llamadas ajax de larga duración que pueden ser interrumpidas por 1) el usuario navega o 2) algún tipo de conexión temporal / falla del servidor. Quiero que el controlador de errores se ejecute solo para la conexión / falla del servidor y no para el usuario que se aleja.

Primero probé la respuesta de Alastair Pitts, pero no funcionó porque tanto las solicitudes abortadas como la falla de conexión establecieron el código de estado y readyState en 0. Luego, probé la respuesta de sieppl; tampoco funcionó porque en ambos casos, no se da respuesta, por lo tanto no hay encabezado.

La única solución que me funcionó es configurar un oyente para window.onbeforeunload, que establece una variable global para indicar que la página se ha descargado. El controlador de errores puede verificar y solo llamar al controlador de errores solo si la página no se ha descargado.

var globalVars = {unloaded:false};
$(window).bind('beforeunload', function(){
    globalVars.unloaded = true;
});
...
$.ajax({
    error: function(jqXHR,status,error){
        if (globalVars.unloaded)
            return;
    }
});
codificador azul
fuente
4
Esto no funciona si una solicitud ajax es interrumpida por JavaScript
Sano J
1
Ésta no es una respuesta válida. En antes de la descarga se puede cancelar la descarga. Si eso sucede, se ignorarán todos los errores posteriores de Ajax.
PERDIDO
@LOST El beforeunloadcontrolador lo define el usuario. ¿Por qué establecería globalVars.unloaded en truesi va a cancelar la descarga con el mismo método?
bluecollarcoder
@bluecollarcoder Todo lo que digo es que si tienes un gran proyecto, donde enfrentas este problema, debes ir y arreglar todos los controladores antes de descargarlos, no es suficiente con agregar uno nuevo que proporcionaste.
PERDIDO
beforeunloadno se llama cuando el usuario navega a otra página o se llama demasiado tarde?
Christophe Roussy
43

En jQuery moderno, puede verificar si request.statusTextes igual a 'abort':

error: function (request, textStatus, errorThrown) {
    if (request.statusText =='abort') {
        return;
    }
}
Udi
fuente
4
en Chrome, puedo buscar "abortar". en firefox, obtengo "error". La solución de @bluecollarcoder parece la mejor para nosotros.
foxontherock
Sí, esto varía según el navegador (los problemas web habituales ...)
Christophe Roussy
21

Algo que encontré es que cuando hay una solicitud abortada, el statusy / o readyStateigual 0.

En mi controlador de errores global, tengo una marca en la parte superior del método:

$(document).ajaxError(function (e, jqXHR, ajaxSettings, thrownError) {
    //If either of these are true, then it's not a true error and we don't care
    if (jqXHR.status === 0 || jqXHR.readyState === 0) {
        return;
    }

    //Do Stuff Here
});

He descubierto que esto funciona perfectamente para mí. Espero que esto te ayude a ti oa cualquier otra persona que se encuentre con esto :)

Alastair Pitts
fuente
3
Obtengo el mismo estado y readyState si ajax no pudo conectarse al servidor para empezar. Pero este es el error que quiero manejar. Solo abortado no.
Mitar
Sí, esto enmascarará otros errores que desee ver.
Christophe Roussy
10

Querrá ver el argumento textStatus pasado a su función de error. Según http://api.jquery.com/jQuery.ajax/ , puede tomar los valores "éxito", "no modificado", "error", "tiempo de espera", "abortar" o "error de análisis". "abortar" es obviamente lo que quiere comprobar.

Notas más largas aquí: jquery-gotcha-error-callback-triggered-on-xhr-abort

Paul Rademacher
fuente
Creo que jugamos con esto y no logró detectar el tipo de mensajes de error de aborto que teníamos.
sieppl
5

Debido a que la respuesta de bluecollarcoders no funciona para solicitudes ajax abortadas por javascript, aquí está mi solución:

var unloaded = false;
...
$(window).bind('beforeunload', function(){
    unloaded = true;
});


$(document).ajaxError(function(event, request, settings) {
    if (unloaded || request.statusText == "abort") {
        return;
    }
    ...
}

p.ej

handler = jQuery.get("foo")
handler.abort()

ahora será ignorado por el controlador ajaxError

Sano J
fuente
3

Sobre la base de la respuesta de Alastair Pitts , también puede hacer esto para tener mensajes más informativos:

$(document).ajaxError(function (e, jqXHR, ajaxSettings, thrownError)
{
    {
        if (jqXHR.status === 0)
        {
            alert('Not connect.\n Verify Network.');
        } else if (jqXHR.status == 404)
        {
            alert('Requested page not found. [404]');
        } else if (jqXHR.status == 500)
        {
            alert('Internal Server Error [500].');
        } else if (exception === 'parsererror')
        {
            alert('Requested JSON parse failed.');
        } else if (exception === 'timeout')
        {
            alert('Time out error.');
        } else if (exception === 'abort')
        {
            alert('Ajax request aborted.');
        } else
        {
            alert('Uncaught Error.\n' + jqXHR.responseText);
        }
    }
});
Leniel Maccaferri
fuente
2
$(document).ajaxError(function(event, jqXHR, ajaxSettings, thrownError) {

    if (!jqXHR.getAllResponseHeaders()) {
        return;
    }           
}); 
sieppl
fuente
1
Tampoco ayuda. Tanto para las solicitudes abortadas como para los errores de conexión al servidor, los encabezados de respuesta están vacíos.
Clovis Six
@ClovisSix Sí, la solución anterior verifica si el encabezado de respuesta está vacío y elimina los mensajes de error irritantes. Funciona bien en varios sistemas comerciales que ejecutamos. ¿Puede dar más detalles sobre lo que intenta lograr / es su problema?
sieppl
Estamos mostrando mensajes si alguna de nuestras solicitudes no se puede conectar al servidor. No los mostramos en el aborto manual, pero el mayor problema fue cuando el usuario navegó a la página siguiente, lo que generó errores de conexión y no había forma de diferenciar entre una solicitud abortada y un error de conexión. Resolví el problema configurando una var en window.onbeforeunload. Que prácticamente detecta un aborto manual.
Clovis Six
También aquí con más detalles: ilikestuffblog.com/2009/11/30/…
Christophe Roussy
0

Tuve el mismo problema aquí, y lo que hice como solución fue establecer una var de "aborto" justo antes de la llamada de abort (), como se muestra a continuación:

aborting = true;
myAjax.abort();

y solo muestra el error en el controlador de errores de la solicitud ajax, si abortar no es cierto.

$.ajax({
    [..]
    error: function() {
        if ( !aborting ) {
            // do some stuff..
        }
        aborting = false;
    }
});
Diego Malone
fuente
0

Si aborta la solicitud ajax manualmente, puede hacer lo siguiente:

var xhr;
function queryData () {
    if (xhr) {
      // tag it's been aborted
      xhr.hasAborted = true;

      // manually canceled request
      xhr.abort();
    }

    xhr = $.ajax({
        url: '...',
        error: function () {
            if (!xhr.hasAborted) {
                console.log('Internal Server Error!');
            }
        },
        complete: function () {
           xhr = null;
        }
    });
}
Cielo
fuente