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?


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


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;
    }
});

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;
    }
}

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 :)


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


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


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);
        }
    }
});

2
$(document).ajaxError(function(event, jqXHR, ajaxSettings, thrownError) {

    if (!jqXHR.getAllResponseHeaders()) {
        return;
    }           
}); 

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;
    }
});

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;
        }
    });
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.