Obsługa jQuery.ajax kontynuuje odpowiedzi: „sukces:” czy „.done”?

309

Pracuję z jQuery i AJAX od kilku tygodni i widziałem dwa różne sposoby „kontynuowania” skryptu po wykonaniu połączenia: success:i .done.

Z streszczenia z dokumentacji jQuery otrzymujemy:

.done (): Opis: Dodaj programy obsługi, które mają być wywoływane, gdy zostanie rozstrzygnięty obiekt Odroczony.

sukces: (opcja .ajax ()): Funkcja, która ma zostać wywołana, jeśli żądanie się powiedzie.

Tak więc oboje robią coś po zakończeniu / rozwiązaniu wywołania AJAX. Czy mogę używać jednego lub drugiego losowo? Jaka jest różnica i kiedy jedno jest używane zamiast drugiego?

Claudio
źródło

Odpowiedzi:

469

successto tradycyjna nazwa wywołania zwrotnego powodzenia w jQuery, zdefiniowana jako opcja w wywołaniu ajax. Ponieważ jednak implementacja $.Deferredsi bardziej wyrafinowane wywołania zwrotne donejest preferowanym sposobem realizacji wywołań zwrotnych powodzenia, ponieważ można je wywołać w dowolnym deferred.

Na przykład sukces:

$.ajax({
  url: '/',
  success: function(data) {}
});

Na przykład zrobione:

$.ajax({url: '/'}).done(function(data) {});

Zaletą donejest to, że zwracana wartość $.ajaxjest teraz odroczoną obietnicą, którą można powiązać z dowolnym innym miejscem w aplikacji. Powiedzmy, że chcesz wykonać to wywołanie ajax z kilku różnych miejsc. Zamiast przechodzącą w funkcji sukcesu jako opcja do funkcji sprawia, że ten ajax połączeń, można po prostu mieć powrotu funkcji $.ajaxsam i powiązać wywołania zwrotne z done, fail, then, czy cokolwiek innego. Pamiętaj, że alwaysjest to wywołanie zwrotne, które zostanie uruchomione niezależnie od tego, czy żądanie zakończy się powodzeniem, czy nie. donezostaną uruchomione tylko w przypadku sukcesu.

Na przykład:

function xhr_get(url) {

  return $.ajax({
    url: url,
    type: 'get',
    dataType: 'json',
    beforeSend: showLoadingImgFn
  })
  .always(function() {
    // remove loading image maybe
  })
  .fail(function() {
    // handle request failures
  });

}

xhr_get('/index').done(function(data) {
  // do stuff with index data
});

xhr_get('/id').done(function(data) {
  // do stuff with id data
});

Ważną korzyścią z punktu widzenia łatwości konserwacji jest to, że mechanizm ajax został zawinięty w funkcję specyficzną dla aplikacji. Jeśli zdecydujesz, że chcesz, aby Twoje $.ajaxwywołanie działało w przyszłości inaczej, lub użyjesz innej metody ajax lub odejdziesz od jQuery, musisz tylko zmienić xhr_getdefinicję (pamiętaj, aby zwrócić obietnicę lub przynajmniej donemetodę, w przypadek z powyższego przykładu). Wszystkie pozostałe odniesienia w aplikacji mogą pozostać takie same.

Jest o wiele więcej (znacznie fajniejszych) rzeczy, które możesz zrobić $.Deferred, z których jednym jest pipeuruchomienie błędu zgłoszonego przez serwer błędu, nawet jeśli $.ajaxsamo żądanie się powiedzie. Na przykład:

function xhr_get(url) {

  return $.ajax({
    url: url,
    type: 'get',
    dataType: 'json'
  })
  .pipe(function(data) {
    return data.responseCode != 200 ?
      $.Deferred().reject( data ) :
      data;
  })
  .fail(function(data) {
    if ( data.responseCode )
      console.log( data.responseCode );
  });
}

xhr_get('/index').done(function(data) {
  // will not run if json returned from ajax has responseCode other than 200
});

Przeczytaj więcej o $.Deferredtutaj: http://api.jquery.com/category/deferred-object/

UWAGA : Począwszy od jQuery 1.8, pipeprzestarzała na korzyść używania thendokładnie w ten sam sposób.

glortho
źródło
2
Zastanawiam się, jak zdefiniowane są interakcje success:/ .done(), jeśli w ogóle. Np. Czy success:właśnie został wdrożony jako pierwszy w .done()tych dniach?
6
Masz na myśli, jeśli masz zarówno jedno, jak success:i .donejedno wywołanie ajax? Dobre pytanie. Ponieważ wszystkie inne wywołania zwrotne są wywoływane w kolejności, w jakiej są powiązane, domyślam się, że tak, successjest wywoływane jako pierwsze.
glortho
1
Bardzo fajny post! Przy okazji w wywołaniu zwrotnym potoku nie powinieneś wywoływać funkcji potoku z parametrem jqXHR w celu sprawdzenia odpowiedzi statusu? Np .: .pipe (funkcja (data, textStatus, jqXHR) {if (jqXHR.status == 200) {...
Eder
@Eder Scenariusz, który rozwiązuję przy użyciu tego zastosowania, pipejest taki, w którym samo żądanie się powiedzie, ale skrypt na serwerze nie zwrócił tego, czego szukałeś. Możesz nie chcieć rzucić rzeczywistej liczby 404 lub 500 po stronie serwera, ponieważ chcesz znacząco rozróżnić odpowiedzi HTTP od odpowiedzi aplikacji. Ustawienie kodu odpowiedzi w JSON, a następnie użycie w pipeten sposób pozwala obsługiwać różnego rodzaju błędy z większym niuansami.
glortho
Inną ważną zaletą korzystania z obietnic jest to, że kod staje się znacznie bardziej czytelny i pozwala uniknąć „piekła zwrotnego”. Jest to szczególnie prawdziwe, gdy masz wiele wywołań zwrotnych, które chcesz uruchomić po zakończeniu poprzedniego. Z obietnicami wyglądałoby to tak: myPromiseCall.then (..). Następnie (..) zamiast zagnieżdżonej skomplikowanej struktury wywołań zwrotnych używanych z opcją sukcesu.
BornToCode,
5

Jeśli potrzebujesz async: falsew swoim ajax, powinieneś użyć successzamiast .done. W przeciwnym razie lepiej użyć .done. To jest z oficjalnej strony jQuery :

Począwszy od jQuery 1.8 użycie async: false z jqXHR ($ .Deferred) jest przestarzałe; Państwo musi wykorzystać sukces / błąd / kompletne opcje wywołania zwrotnego zamiast odpowiednich metod obiektu jqXHR takich jak jqXHR.done () .

AmirHossein Manian
źródło
Kto wspomniał async:false?
Liam
$.ajax({ url: req_url, ..., async: false, success: function (result, status, req) { }, error: function (jqXHR, status) { } });
AmirHossein Manian
0

Z dokumentacji JQuery

Obiekty jqXHR zwrócone przez $.ajax()jQuery 1.5 implementują interfejs Obietnicy, nadając im wszystkie właściwości, metody i zachowanie Obietnicy (zobacz Odroczony obiekt, aby uzyskać więcej informacji). Te metody pobierają jeden lub więcej argumentów funkcji, które są wywoływane po $.ajax()zakończeniu żądania. Umożliwia to przypisanie wielu wywołań zwrotnych do pojedynczego żądania, a nawet przypisanie wywołań zwrotnych po zakończeniu żądania. (Jeśli żądanie jest już ukończone, wywołanie zwrotne jest natychmiast uruchamiane.) Dostępne metody promise obiektu jqXHR obejmują:

jqXHR.done(function( data, textStatus, jqXHR ) {});

Alternatywna konstrukcja do opcji wywołania zwrotnego powodzenia, patrz deferred.done()szczegóły implementacji.

jqXHR.fail(function( jqXHR, textStatus, errorThrown ) {});

Alternatywna konstrukcja dla opcji wywołania zwrotnego błędu, .fail()metoda zastępuje przestarzałą metodę .error (). Szczegółowe informacje dotyczące implementacji można znaleźć w deferred.fail ().

jqXHR.always(function( data|jqXHR, textStatus, jqXHR|errorThrown ) { }); 

(dodano w jQuery 1.6) Alternatywna konstrukcja do pełnej opcji wywołania zwrotnego, .always()metoda zastępuje przestarzałą .complete()metodę.

W odpowiedzi na pomyślne żądanie argumenty funkcji są takie same jak argumenty .done(): data, textStatus i obiektu jqXHR. W przypadku nieudanych żądań argumenty są takie same jak w przypadku .fail(): obiektu jqXHR, textStatus i errorThrown. Zobacz deferred.always()szczegóły implementacji.

jqXHR.then(function( data, textStatus, jqXHR ) {}, function( jqXHR, textStatus, errorThrown ) {});

Zawiera funkcjonalność .done()i .fail()metod, umożliwiając (od jQuery 1.8) manipulowanie leżącą u podstaw obietnicą. Szczegółowe informacje .then()na temat implementacji można znaleźć w części odroczonej .

Wycofanie Wskazówki:jqXHR.success() , jqXHR.error()i jqXHR.complete()zwrotne są usuwane jako jQuery 3.0. Można użyć jqXHR.done(), jqXHR.fail()i jqXHR.always()zamiast tego.

Sasmit
źródło