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?


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


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

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

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


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


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


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

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

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

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


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

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;
        }
    });
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.