Jquery Ajax Fehlerbehandlung zum Ignorieren abgebrochen

80

Ich möchte eine globale Fehlerbehandlungsmethode für Ajax-Aufrufe haben. Dies ist, was ich jetzt habe:

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

Ich muss den Fehler von ignorieren aborted. errorThrownist null und textStatusist error. Wie überprüfe ich aborted?

Shawn Mclean
quelle
4
Für mich ist textStatus "abbrechen". Ich sehe, das ist eine alte Frage - vielleicht hat sie sich geändert.
Jackocnr
Für mich ist es immer noch "Fehler".
Jānis Elmeris
Ja, leider variiert es je nach Browser.
Christophe Roussy
Siehe auch: github.com/angular/angular.js/issues/15924 (2017)
Christophe Roussy
1
Wenn Sie abortmanuell anrufen (und ich bin nicht sicher, wann es sonst angerufen wird), können Sie die Fehlermeldung übergeben : abort("abort").
MyiEye

Antworten:

52

Ich musste mich heute mit dem gleichen Anwendungsfall befassen. Die App, an der ich arbeite, hat diese lang laufenden Ajax-Aufrufe, die unterbrochen werden können durch 1) den Benutzer, der weg navigiert, oder 2) eine Art vorübergehenden Verbindungs- / Serverausfall. Ich möchte, dass der Fehlerbehandler nur für Verbindungs- / Serverfehler ausgeführt wird und nicht für den Benutzer, der weg navigiert.

Ich habe zuerst die Antwort von Alastair Pitts versucht, aber es hat nicht funktioniert, da sowohl abgebrochene Anforderungen als auch Verbindungsfehler den Statuscode und readyState auf 0 gesetzt haben. Als nächstes habe ich die Antwort von sieppl versucht. hat auch nicht funktioniert, da in beiden Fällen keine Antwort gegeben wird, also kein Header.

Die einzige Lösung, die für mich funktioniert hat, besteht darin, einen Listener für window.onbeforeunload festzulegen, der eine globale Variable festlegt, die angibt, dass die Seite entladen wurde. Der Fehlerbehandler kann dann den Fehlerbehandler nur dann überprüfen und aufrufen, wenn die Seite nicht entladen wurde.

var globalVars = {unloaded:false};
$(window).bind('beforeunload', function(){
    globalVars.unloaded = true;
});
...
$.ajax({
    error: function(jqXHR,status,error){
        if (globalVars.unloaded)
            return;
    }
});
Bluecollarcoder
quelle
4
Dies funktioniert nicht, wenn eine Ajax-Anfrage von JavaScript unterbrochen wird
Sano J
1
Dies ist keine gültige Antwort. Vor dem Entladen kann das Entladen abgebrochen werden. In diesem Fall werden alle nachfolgenden Ajax-Fehler ignoriert.
VERLOREN
@LOST Der beforeunloadHandler ist benutzerdefiniert. Warum sollten Sie globalVars.unloaded auf setzen, truewenn Sie das Entladen mit derselben Methode abbrechen möchten ?
Bluecollarcoder
@bluecollarcoder Ich sage nur, wenn Sie ein großes Projekt haben, bei dem Sie mit diesem Problem konfrontiert sind, müssen Sie alle darin enthaltenen Handlders reparieren, bevor Sie sie herunterladen. Es reicht nicht aus, nur ein neues hinzuzufügen, das Sie bereitgestellt haben.
LOST
beforeunloadwird nicht aufgerufen, wenn der Benutzer zu einer anderen Seite navigiert oder zu spät angerufen wird?
Christophe Roussy
41

In der modernen jQuery können Sie einfach überprüfen, ob request.statusTextFolgendes gleich ist 'abort':

error: function (request, textStatus, errorThrown) {
    if (request.statusText =='abort') {
        return;
    }
}
Udi
quelle
4
In Chrom kann ich nach "Abbruch" suchen. In Firefox erhalte ich "Fehler". Die Lösung von @bluecollarcoder scheint für uns die beste zu sein.
Foxontherock
Ja, dies variiert je nach Browser (die üblichen Webprobleme ...)
Christophe Roussy
21

Etwas, das ich gefunden habe, ist, dass, wenn es eine abgebrochene Anfrage gibt, die statusund / oder readyStategleich ist 0.

In meinem globalen Fehlerbehandler befindet sich oben in der Methode eine Überprüfung:

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

Ich habe festgestellt, dass dies perfekt für mich funktioniert. Hoffe das hilft dir oder irgendjemand anderem, der darauf stößt :)

Alastair Pitts
quelle
3
Ich erhalte den gleichen Status und readyState, wenn Ajax zunächst keine Verbindung zum Server herstellen konnte. Aber das ist der Fehler, den ich behandeln möchte. Nur nicht abgebrochen.
Mitar
Ja, dies maskiert andere Fehler, die Sie sehen möchten.
Christophe Roussy
10

Sie sollten sich das textStatus-Argument ansehen, das an Ihre Fehlerfunktion übergeben wurde. Laut http://api.jquery.com/jQuery.ajax/ können die Werte "Erfolg", "Nicht geändert", "Fehler", "Zeitüberschreitung", "Abbruch" oder "Parsererror" angenommen werden. "Abbruch" ist offensichtlich das, gegen das Sie prüfen möchten.

Längere Hinweise hier: jquery-gotcha-error-callback-triggered-on-xhr-abort

Paul Rademacher
quelle
Ich denke, wir haben damit herumgespielt und es ist nicht gelungen, die Art von Abbruchfehlermeldungen zu erkennen, die wir hatten.
Sieppl
4

Da die Antwort von bluecollarcoders bei Ajax-Anfragen, die durch Javascript abgebrochen wurden, nicht funktioniert, ist hier meine Lösung:

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


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

z.B

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

wird jetzt vom AjaxError-Handler ignoriert

Sano J.
quelle
3

Aufbauend auf der Antwort von Alastair Pitts'a können Sie dies auch tun, um informativere Nachrichten zu erhalten:

$(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
quelle
2
$(document).ajaxError(function(event, jqXHR, ajaxSettings, thrownError) {

    if (!jqXHR.getAllResponseHeaders()) {
        return;
    }           
}); 
sieppl
quelle
1
Hilft auch nicht. Sowohl für abgebrochene Anforderungen als auch für Verbindungsfehler zum Server sind die Antwortheader leer.
Clovis Six
@ClovisSix Ja, die obige Lösung prüft, ob der Antwortheader leer ist, und unterdrückt irritierende Fehlermeldungen. Funktioniert gut auf mehreren kommerziellen Systemen, die wir ausführen. Können Sie bitte näher erläutern, was Sie erreichen möchten / was Ihr Problem ist?
Sieppl
Wir zeigen Nachrichten an, wenn eine unserer Anfragen keine Verbindung zum Server herstellen kann. Wir zeigen sie nicht beim manuellen Abbruch, aber das größte Problem war, als der Benutzer zur nächsten Seite navigierte, die Verbindungsfehler verursachte und es keine Möglichkeit gab, zwischen einer abgebrochenen Anforderung und einem Verbindungsfehler zu unterscheiden. Ich habe das Problem behoben, indem ich eine Variable für window.onbeforeunload festgelegt habe. Was so ziemlich einen manuellen Abbruch erkennt.
Clovis Six
Auch hier mit mehr Details: ilikestuffblog.com/2009/11/30/…
Christophe Roussy
0

Ich hatte hier das gleiche Problem, und als Lösung habe ich kurz vor dem Aufruf von abort () eine "aborting" -Vari festgelegt, wie folgt:

aborting = true;
myAjax.abort();

und zeigen Sie den Fehler nur im Fehlerhandler der Ajax-Anforderung an, wenn der Abbruch nicht wahr ist.

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

Wenn Sie die Ajax-Anforderung manuell abbrechen, können Sie Folgendes tun:

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