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?


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


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

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

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


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


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


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

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

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

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

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;
        }
    });
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.