web-dev-qa-db-fra.com

Traitement des erreurs JQuery Ajax à ignorer abandonné

Je souhaite disposer d'une méthode globale de traitement des erreurs pour les appels ajax. Voici ce que j'ai maintenant:

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

J'ai besoin d'ignorer l'erreur de aborted. errorThrown est null et textStatus est error. Comment puis-je vérifier aborted?

74
Shawn Mclean

J'ai eu à traiter avec le même cas d'utilisation aujourd'hui. L'application sur laquelle je travaille a ces appels ajax de longue durée qui peuvent être interrompus par 1) l'utilisateur qui s'éloigne ou 2) un type d'échec de connexion/serveur temporaire. Je veux que le gestionnaire d'erreurs ne s'exécute que pour une défaillance de connexion/serveur et non pour l'utilisateur qui s'en va.

J'ai d'abord essayé la réponse de Alastair Pitts, mais cela n'a pas fonctionné car les demandes abandonnées et le code d'état du jeu avec échec de connexion et readyState étaient à 0. J'ai ensuite essayé la réponse de sieppl; également ne fonctionnait pas parce que dans les deux cas, aucune réponse n’est donnée, donc aucun en-tête.

La seule solution qui a fonctionné pour moi consiste à définir un écouteur pour window.onbeforeunload, qui définit une variable globale pour indiquer que la page a été déchargée. Le gestionnaire d'erreurs peut alors vérifier et appeler le gestionnaire d'erreurs uniquement si la page n'a pas été déchargée.

var globalVars = {unloaded:false};
$(window).bind('beforeunload', function(){
    globalVars.unloaded = true;
});
...
$.ajax({
    error: function(jqXHR,status,error){
        if (globalVars.unloaded)
            return;
    }
});
49
bluecollarcoder

Dans jQuery moderne, vous pouvez simplement vérifier si request.statusText est égal à 'abort':

error: function (request, textStatus, errorThrown) {
    if (request.statusText =='abort') {
        return;
    }
}
36
Udi

Quelque chose que j’ai trouvé est que quand il y a une demande abandonnée, le status et/ou readyState est égal à 0.

Dans mon gestionnaire d'erreurs global, j'ai un contrôle en haut de la méthode:

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

J'ai trouvé cela fonctionne parfaitement pour moi. J'espère que cela vous aide, ou quiconque d'autre qui se heurte à cela :)

21
Alastair Pitts

Vous voudrez examiner l'argument textStatus transmis à votre fonction d'erreur. Selon http://api.jquery.com/jQuery.ajax/ , il peut prendre les valeurs "succès", "non modifié", "erreur", "délai d'attente", "abandon" ou "analyseur syntaxique" . "abort" est évidemment ce que vous voulez vérifier.

Notes plus longues ici: jquery-gotcha-error-callback-triggered-on-xhr-abort

10
Paul Rademacher

Puisque bluecollarcoders answer ne fonctionne pas pour les demandes ajax abandonnées par javascript, voici ma solution:

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


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

par exemple.

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

sera maintenant ignoré par le gestionnaire ajaxError

4
Sano J

En vous appuyant sur Alastair Pitts'a answer , vous pouvez également le faire pour diffuser des messages plus informatifs:

$(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);
        }
    }
});
3
Leniel Maccaferri
$(document).ajaxError(function(event, jqXHR, ajaxSettings, thrownError) {

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

La solution rapide (et sale):

if (status === 0) { // or -1 depending on where you do this
  setTimeout(function() {
    // error handling here
  }, 2000); // 2 seconds, or use more ...
}

si le statut d'erreur xhr est 0 (*), définissez un délai de délai de 2 secondes autour du code de traitement des erreurs. À ce moment, le navigateur a déjà chargé le nouveau contexte de page et l'erreur ne s'affiche jamais.

Si l'erreur n'est pas due à un abandon en naviguant sur une autre page, l'erreur s'affichera avec un certain retard.

* NOTE: en fonction des bibliothèques utilisées et du gestionnaire d'erreurs que vous utilisez, il peut être égal à -1 au lieu de zéro (Angular ...) ou autre chose.

IMPORTANT: le texte du statut peut varier d’un navigateur à l’autre et d’une bibliothèque à l’autre, vous ne pouvez donc pas vous fier à elle. Veuillez me le faire savoir dans les commentaires si vous trouvez une solution multi-navigateur.

0

J'ai eu le même problème ici, et ce que j'ai fait comme solution a été de définir une variable "d'abandon" juste avant l'appel de abort (), comme ci-dessous:

aborting = true;
myAjax.abort();

et ne montre que l'erreur sur le gestionnaire d'erreurs de la demande ajax, si abort n'est pas vrai.

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

Si vous abandonnez la demande ajax manuellement, vous pouvez procéder comme suit:

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