Obsługa błędów JQuery Ajax w celu zignorowania przerwano

81

Chcę mieć globalną metodę obsługi błędów dla wywołań ajax, oto co mam teraz:

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

Muszę zignorować błąd aborted. errorThrownjest null i textStatusjest error. Jak sprawdzić aborted?

Shawn Mclean
źródło
4
Dla mnie textStatus to "abort". Widzę, że to stare pytanie - może się zmieniło.
jackocnr
Dla mnie to nadal „błąd”.
Jānis Elmeris,
Tak, niestety różni się w zależności od przeglądarki.
Christophe Roussy
Zobacz także: github.com/angular/angular.js/issues/15924 (2017)
Christophe Roussy
1
Jeśli dzwonisz abortręcznie (a nie jestem pewien, kiedy indziej, że to się nazywa) można przekazać w komunikacie o błędzie: abort("abort").
MyiEye,

Odpowiedzi:

52

Dzisiaj miałem do czynienia z tym samym przypadkiem użycia. Aplikacja, nad którą pracuję, ma te długotrwałe wywołania ajax, które mogą zostać przerwane przez 1) nawigację użytkownika lub 2) tymczasową awarię połączenia / serwera. Chcę, aby program obsługi błędów działał tylko w przypadku awarii połączenia / serwera, a nie dla użytkownika odchodzącego.

Najpierw wypróbowałem odpowiedź Alastaira Pittsa, ale nie zadziałała, ponieważ zarówno przerwane żądania, jak i błąd połączenia ustawiają kod stanu i readyState na 0. Następnie wypróbowałem odpowiedź sieppl; również nie zadziałało, ponieważ w obu przypadkach nie ma odpowiedzi, a więc nie ma nagłówka.

Jedynym rozwiązaniem, które zadziałało, jest ustawienie nasłuchiwania dla window.onbeforeunload, które ustawia zmienną globalną wskazującą, że strona została wyładowana. Procedura obsługi błędów może następnie sprawdzić i wywołać procedurę obsługi błędów tylko wtedy, gdy strona nie została wyładowana.

var globalVars = {unloaded:false};
$(window).bind('beforeunload', function(){
    globalVars.unloaded = true;
});
...
$.ajax({
    error: function(jqXHR,status,error){
        if (globalVars.unloaded)
            return;
    }
});
bluecollarcoder
źródło
4
To nie działa, jeśli żądanie Ajax zostanie przerwane przez JavaScript
Sano J,
1
To nie jest prawidłowa odpowiedź. Przed rozładunkiem można anulować rozładunek. Jeśli tak się stanie, wszystkie kolejne błędy Ajax zostaną zignorowane.
LOST
@LOST Program beforeunloadobsługi jest zdefiniowany przez użytkownika. Dlaczego miałbyś ustawić globalVars.unloaded na, truejeśli zamierzasz anulować wyładowywanie w ten sam sposób?
bluecollarcoder
@bluecollarcoder Mówię tylko, że jeśli masz duży projekt, w którym napotykasz ten problem, musisz go naprawić przed załadowaniem w nim hanldów, nie wystarczy po prostu dodać nowy, który podałeś.
LOST
beforeunloadnie jest wywoływana, gdy użytkownik przechodzi na inną stronę lub dzwoni za późno?
Christophe Roussy
43

W nowoczesnym jQuery możesz po prostu sprawdzić, czy request.statusTextjest równe 'abort':

error: function (request, textStatus, errorThrown) {
    if (request.statusText =='abort') {
        return;
    }
}
Udi
źródło
4
w chrome mogę sprawdzić "abort". w przeglądarce Firefox pojawia się komunikat „błąd”. Rozwiązanie od @bluecollarcoder wydaje się dla nas najlepsze.
foxontherock
Tak, to zależy od przeglądarki (typowe problemy z siecią ...)
Christophe Roussy
21

Coś, co znalazłem, jest takie, że gdy istnieje przerwane żądanie, statusi / lub readyStaterówne 0.

W moim globalnym module obsługi błędów mam zaznaczenie na górze metody:

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

Odkryłem, że to działa idealnie dla mnie. Mam nadzieję, że to pomoże Tobie lub komukolwiek, kto w to wpadnie :)

Alastair Pitts
źródło
3
Otrzymuję ten sam status i readyState, jeśli ajax nie mógł połączyć się z serwerem na początku. Ale to jest błąd, z którym chcę się uporać. Tylko nie przerwano.
Mitar
Tak, spowoduje to zamaskowanie innych błędów, które chcesz zobaczyć.
Christophe Roussy
10

Będziesz chciał przyjrzeć się argumentowi textStatus przekazanemu do funkcji błędu. Według http://api.jquery.com/jQuery.ajax/ , może on przyjmować wartości „sukces”, „notmodified”, „error”, „timeout”, „abort” lub „parsererror”. „Przerwij” jest oczywiście tym, przed czym chcesz sprawdzić.

Dłuższe notatki tutaj: jquery-gotcha-error-callback-triggered-on-xhr-abort

Paul Rademacher
źródło
Myślę, że bawiliśmy się tym i nie udało się wykryć tego rodzaju komunikatów o błędach przerywania, które mieliśmy.
sieppl
5

Ponieważ odpowiedź bluecollarcoders nie działa dla żądań Ajax przerwanych przez javascript, oto moje rozwiązanie:

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


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

na przykład

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

będzie teraz ignorowany przez moduł obsługi ajaxError

Sano J
źródło
3

Opierając się na odpowiedzi Alastaira Pittsa , możesz to również zrobić, aby uzyskać więcej informacji:

$(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
źródło
2
$(document).ajaxError(function(event, jqXHR, ajaxSettings, thrownError) {

    if (!jqXHR.getAllResponseHeaders()) {
        return;
    }           
}); 
sieppl
źródło
1
To też nie pomaga. Zarówno w przypadku przerwanych żądań, jak i błędów połączenia z serwerem nagłówki odpowiedzi są puste.
Clovis Six
@ClovisSix Tak, powyższe rozwiązanie sprawdza, czy nagłówek odpowiedzi jest pusty i eliminuje irytujące komunikaty o błędach. Działa dobrze na wielu komercyjnych systemach, które obsługujemy. Czy możesz podać więcej szczegółów, co próbujesz osiągnąć / na czym polega problem?
sieppl
Wyświetlamy komunikaty, jeśli którekolwiek z naszych żądań nie może połączyć się z serwerem. Nie pokazujemy ich po ręcznym przerwaniu, ale największym problemem było to, że użytkownik przeszedł do następnej strony, co spowodowało błędy połączenia i nie było możliwości odróżnienia przerwanego żądania od błędu połączenia. Rozwiązałem ten problem, ustawiając zmienną na window.onbeforeunload. Co prawie wykrywa ręczne przerwanie.
Clovis Six,
Również tutaj z dodatkowymi szczegółami: ilikestuffblog.com/2009/11/30/…
Christophe Roussy
0

Miałem tutaj ten sam problem, a jako rozwiązanie zastosowałem zmienną „przerywającą” tuż przed wywołaniem abort (), jak poniżej:

aborting = true;
myAjax.abort();

i pokazuje tylko błąd w obsłudze błędów żądania ajax, jeśli abort nie jest prawdą.

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

Jeśli ręcznie anulujesz żądanie Ajax, możesz zrobić to w następujący sposób:

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;
        }
    });
}
Niebo
źródło