Czytałem o odroczeniu i obietnicach jQuery i nie widzę różnicy między korzystaniem z .then()
& .done()
dla udanych połączeń zwrotnych. Wiem, że Eric Hynds wspomina o tym .done()
i .success()
odwzorowuje tę samą funkcjonalność, ale chyba tak, .then()
ponieważ wszystkie wywołania zwrotne są wywoływane po zakończeniu udanej operacji.
Czy ktoś może oświecić mnie do prawidłowego użytkowania?
jquery
promise
jquery-deferred
screenm0nkey
źródło
źródło
Odpowiedzi:
Załączone wywołania zwrotne
done()
zostaną uruchomione, gdy odroczone zostanie rozwiązane. Załączone wywołania zwrotnefail()
zostaną uruchomione, gdy odroczone zostanie odrzucone.Przed wersją jQuery 1.8
then()
był tylko cukier syntaktyczny:Od wersji 1.8
then()
jest pseudonimempipe()
i zwraca nową obietnicę, więcej informacji znajdziesz tutajpipe()
.success()
ierror()
są dostępne tylko dlajqXHR
obiektu zwróconego przez wywołanie doajax()
. Są to proste aliasy dladone()
ifail()
odpowiednio:Ponadto
done()
nie ogranicza się do pojedynczego wywołania zwrotnego i odfiltrowuje niefunkcje (chociaż w wersji 1.8 występuje błąd dotyczący ciągów znaków, który należy naprawić w wersji 1.8.1):To samo dotyczy
fail()
.źródło
then
zwrócenie nowej obietnicy było kluczową rzeczą, której mi brakowało. Nie mogłem zrozumieć, dlaczego łańcuch taki$.get(....).done(function(data1) { return $.get(...) }).done(function(data2) { ... })
zawodzi zdata2
nieokreślonym; kiedy zmieniłodone
sięthen
to działało, bo naprawdę chcą obietnic rurowych razem zamiast dołączać kolejne ładowarki do oryginalnego obietnicy.done
lubthen
? Dlaczego?.then()
).Istnieje również różnica w sposobie przetwarzania wyników zwracanych (nazywa się to łańcuchem,
done
nie łączy się podczasthen
tworzenia łańcuchów połączeń)Zostaną zarejestrowane następujące wyniki:
Podczas
otrzyma:
---------- Aktualizacja:
Btw. Zapomniałem wspomnieć, że jeśli zwrócisz obietnicę zamiast wartości typu atomowego, obietnica zewnętrzna będzie czekać, aż obietnica wewnętrzna zostanie rozwiązana:
w ten sposób bardzo proste staje się komponowanie równoległych lub sekwencyjnych operacji asynchronicznych, takich jak:
Powyższy kod wysyła dwa żądania HTTP równolegle, dzięki czemu żądania są ukończone wcześniej, podczas gdy poniżej te żądania są uruchamiane sekwencyjnie, co zmniejsza obciążenie serwera
źródło
done
nie ma wpływu na wynik, gdythen
zmienia wynik. Ogromny punkt pominięty przez innych imo.then
zmieniło się w wersji 1.8done
ithen
wywołaniami.done
przykładzie. Zmieńthen
napipe
wcześniejszą niż 1.8, aby uzyskaćthen
zachowanie 1.8+ ..done()
ma tylko jedno połączenie zwrotne i jest to połączenie zwrotne zakończone powodzeniem.then()
ma zarówno callback powodzenia, jak i niepowodzenia.fail()
ma tylko jedno niepowodzenie wywołania zwrotnegowięc to od Ciebie zależy, co musisz zrobić ... czy obchodzi Cię, czy się powiedzie, czy nie?
źródło
then()
bardzo się różniądone()
. Jakthen()
często nazywane jest tylko zwrotem sukcesu, twój punkt jest raczej szczegółem niż najważniejszą rzeczą do zapamiętania / poznania. (Nie można powiedzieć, jak było przed jQuery 3.0.)deferred.done ()
dodaje procedury obsługi, które mają być wywoływane tylko po rozstrzygnięciu opcji Odroczony . Możesz dodać wiele wywołań zwrotnych, które będą wywoływane.
Możesz także napisać powyżej w ten sposób,
deferred.then ()
dodaje procedury obsługi, które mają być wywoływane, gdy funkcja odroczenia jest rozpatrywana, odrzucana lub wciąż trwa .
źródło
then
zachowuje, jeśli niefail
zostanie udzielone oddzwonienie - a mianowicie nie uchwyceniefail
sprawyJest tak naprawdę dość istotna różnica, o ile Odroczone jQuery mają być implementacjami Obietnic (a jQuery3.0 faktycznie próbuje wprowadzić je w specyfikację).
Kluczowa różnica między wykonaniem / następnie jest taka
.done()
ZAWSZE zwraca te same obietnice / zapakowane wartości, od których zaczął, niezależnie od tego, co robisz lub co zwracasz..then()
zawsze zwraca NOWĄ obietnicę, a ty jesteś odpowiedzialny za kontrolowanie, co ta obietnica jest oparta na funkcji, którą przekazałeś.Przetłumaczone z jQuery na natywne obietnice ES2015,
.done()
jest coś w rodzaju implementacji struktury „dotknij” wokół funkcji w łańcuchu obietnicy, w tym sensie, że jeśli łańcuch jest w stanie „rozstrzygnięcia”, przekaże wartość do funkcji .. , ale wynik tej funkcji NIE wpłynie na sam łańcuch.Oba będą rejestrować 5, a nie 6.
Zauważ, że użyłem done i doneWrap do rejestrowania, a nie. Następnie. To dlatego, że funkcje console.log nie zwracają niczego. A co się stanie, jeśli zdasz. Następnie funkcję, która nic nie zwraca?
To będzie rejestrować:
Co się stało? Kiedy użyłem .the i przekazałem mu funkcję, która niczego nie zwróciła, jej domyślnym rezultatem było „niezdefiniowane” ... co oczywiście zwróciło Obietnicę [niezdefiniowana] do następnej metody, która zalogowała się niezdefiniowana. Tak więc pierwotna wartość, od której zaczęliśmy, została zasadniczo utracona.
.then()
jest w istocie formą kompozycji funkcji: wynik każdego kroku jest wykorzystywany jako argument funkcji w następnym kroku. Właśnie dlatego .done najlepiej jest traktować jako „stuknięcie” -> to nie jest tak naprawdę część kompozycji, tylko coś, co rzuca okiem na wartość na pewnym etapie i uruchamia funkcję przy tej wartości, ale tak naprawdę nie zmienia kompozycja w jakikolwiek sposób.Jest to dość podstawowa różnica i prawdopodobnie istnieje dobry powód, dla którego natywne obietnice nie mają zaimplementowanej metody .done. Nie musimy się zastanawiać, dlaczego nie ma metody .fail, ponieważ jest to nawet bardziej skomplikowane (mianowicie .fail / .catch NIE są dublowaniem funkcji .done / .the -> funkcje w .catch, które zwracają same wartości, nie „zostań” odrzucony tak, jak te przekazane do. następnie rozwiązują!)
źródło
then()
zawsze oznacza, że zostanie wywołany w każdym przypadku. Ale przekazywane parametry są różne w różnych wersjach jQuery.Przed jQuery 1.8
then()
równa siędone().fail()
. Wszystkie funkcje zwrotne mają te same parametry.Ale od jQuery 1.8
then()
zwraca nową obietnicę, a jeśli zwróci wartość, zostanie przekazana do następnej funkcji wywołania zwrotnego.Zobaczmy następujący przykład:
Przed wersją jQuery 1.8 odpowiedź powinna brzmieć
Wszystko
result
zajmuje 3. Ithen()
funkcja zawsze przekazuje ten sam odroczony obiekt do następnej funkcji.Ale od jQuery 1.8 wynik powinien być:
Ponieważ pierwsza
then()
funkcja zwraca nową obietnicę, a wartość 7 (i jest to jedyny parametr, który zostanie przekazany) jest przekazywana do następnejdone()
, więc drugidone()
zapisresult = 7
. Drugithen()
przyjmuje 7 jako wartośća
i przyjmujeundefined
jako wartośćb
, więc drugithen()
zwraca nową obietnicę z parametrem NaN, a ostatnidone()
wypisuje NaN jako wynik.źródło
jQuery.Deferred()
może otrzymać wiele wartości, które właściwie przekazuje do pierwszej.then()
. - Trochę to dziwne ... ponieważ żaden inny.then()
nie może tego zrobić. (Wybrany interfejs przezreturn
może zwrócić tylko jedną wartość.) Język rodzimy JavascriptPromise
tego nie robi. (Szczerze mówiąc, co jest bardziej konsekwentne)Istnieje bardzo proste mapowanie myśli w odpowiedzi, które było nieco trudne do znalezienia w innych odpowiedziach:
done
implementujetap
jak w Bluebird Promisesthen
wdrażathen
jak w obietnicach ES6źródło
Jedynym zastosowaniem
.then()
Są to wady
.done()
resolve()
wywołania (wszystkie.done()
procedury obsługi będą wykonywane synchronicznie)resolve()
może uzyskać wyjątek od zarejestrowanych.done()
programów obsługi (!).done()
połowie zabija odroczonych:.done()
Wozy będą dyskretnie pominięteMyślałem tymczasowo, że to
.then(oneArgOnly)
zawsze wymaga.catch()
, aby żaden wyjątek nie był dyskretnie ignorowany, ale nie jest to już prawdą:unhandledrejection
dzienniki zdarzeń rejestrują nieobsługiwane.then()
wyjątki w konsoli (domyślnie). Bardzo rozsądne!.done()
W ogóle nie ma powodu, by z niego korzystać .Dowód
Poniższy fragment kodu ujawnia, że:
.done()
programy obsługi będą nazywane synchronicznymi w punkcieresolve()
.done()
wpływa naresolve()
rozmówcęresolve()
.done()
rozwiązania.then()
nie ma żadnego z tych problemówunhandledrejection
wydaje się, że środowisko fragmentu nie ma jest)Btw, wyjątki od
.done()
nie mogą być właściwie wychwycone: z powodu synchronicznego wzorca.done()
błąd jest zgłaszany w punkcie.resolve()
(może to być kod biblioteki!) Lub w.done()
wywołaniu, które dołącza sprawcę, jeśli odroczone jest już rozwiązane.źródło
done
nie zostanie wykonane, jeśli poprzednia czynność ma wyjątek. Ale dlaczego miałby być cicho ignorowany, mam na myśli wyjątek, więc dlaczego mówisz, że jest cicho? 2) NienawidzęDeferred
obiektu, ponieważ jego interfejs API jest bardzo, bardzo źle wykonany. Jest to zbyt skomplikowane i mylące. Twój kod tutaj nie pomaga również udowodnić twojego punktu i ma zbyt wiele niepotrzebnej złożoności dla tego, co próbujesz udowodnić. 3) Dlaczegodone
indeksy 2, 4 i 6 są wykonywane przed drugimthen
?.then()
zostaną wywołane, wyjątek (w tych modułach obsługi) podniesiony lub nie. Ale dodanie / pozostała.done()
przerwa.Jest jeszcze jedna istotna różnica w stosunku do jQuery 3.0, która może łatwo prowadzić do nieoczekiwanego zachowania i nie jest wspomniana w poprzednich odpowiedziach:
Rozważ następujący kod:
spowoduje to:
Teraz zamień
done()
nathen()
w tym samym fragmencie:wyjście jest teraz:
Tak więc, dla natychmiastowo rozwiązanych odroczeń, przekazana funkcja
done()
zawsze będzie wywoływana synchronicznie, podczas gdy każdy przekazany argumentthen()
jest wywoływany asynchronicznie.Różni się to od wcześniejszych wersji jQuery, w których oba połączenia zwrotne są wywoływane synchronicznie, jak wspomniano w przewodniku aktualizacji :
źródło
.done()
kończy łańcuch obietnic, upewniając się, że nic więcej nie może załączyć dalszych kroków. Oznacza to, że implementacja obietnicy jQuery może zgłosić dowolny nieobsługiwany wyjątek, ponieważ nikt nie może tego obsłużyć.fail()
.W praktyce, jeśli nie planujesz dołączać kolejnych kroków do obietnicy, powinieneś skorzystać
.done()
. Aby uzyskać więcej informacji, zobacz, dlaczego należy składać obietniceźródło
.done()
nie pełni roli kończącej. Dokumentacja mówi: „Ponieważ deferred.done () zwraca odroczony obiekt, inne metody odroczonego obiektu można powiązać z tym, w tym dodatkowe metody .done ()”..fail()
nie jest wspomniane, ale tak, to też można powiązać.