jQuery Deferred
ma dwie funkcje, które można wykorzystać do implementacji asynchronicznego łączenia funkcji w łańcuchy:
then()
deferred.then( doneCallbacks, failCallbacks ) Returns: Deferred
doneCallbacks Funkcja lub tablica funkcji wywoływana po rozwiązaniu funkcji Deferred .
failCallbacks Funkcja lub tablica funkcji wywoływana w przypadku odrzucenia funkcji Deferred .
pipe()
deferred.pipe( [doneFilter] [, failFilter] ) Returns: Promise
doneFilter Opcjonalna funkcja, która jest wywoływana po rozwiązaniu Deferred .
failFilter Opcjonalna funkcja, która jest wywoływana, gdy Deferred zostanie odrzucona.
Wiem, then()
że trwało to trochę dłużej, niż pipe()
więc ta ostatnia musi przynosić dodatkowe korzyści, ale jaka różnica dokładnie mi umyka. Oba przyjmują prawie te same parametry wywołania zwrotnego, chociaż różnią się nazwą, a różnica między zwróceniem a Deferred
a zwróceniem a Promise
wydaje się niewielka.
Czytałem oficjalne dokumenty w kółko, ale zawsze uważałem je za zbyt „gęste”, by naprawdę zawinąć głowę, a wyszukiwanie znalazło wiele dyskusji na temat jednej lub drugiej funkcji, ale nie znalazłem niczego, co naprawdę wyjaśniałoby różne wady i zalety każdego z nich.
Kiedy więc lepiej używać, then
a kiedy lepiej używać pipe
?
Dodanie
Doskonała odpowiedź Felixa naprawdę pomogła wyjaśnić, czym różnią się te dwie funkcje. Ale zastanawiam się, czy są chwile, w których funkcjonalność then()
jest lepsza niż pipe()
.
Widać, że pipe()
jest potężniejszy niż then()
i wydaje się, że ten pierwszy może zrobić wszystko, co drugi. Jednym z powodów użycia then()
może być fakt, że jego nazwa odzwierciedla jego rolę jako zakończenia łańcucha funkcji przetwarzających te same dane.
Ale czy istnieje przypadek użycia, który wymaga then()
zwrotu oryginału, z Deferred
którym nie można zrobić, pipe()
ponieważ zwraca nowy Promise
?
źródło
Odpowiedzi:
Ponieważ jQuery 1.8
.then
zachowuje się tak samo jak.pipe
:i
Poniższe przykłady mogą być nadal pomocne dla niektórych.
Służą różnym celom:
.then()
ma być używany zawsze, gdy chcesz pracować z wynikiem procesu, tj. jak mówi dokumentacja, gdy odroczony obiekt zostanie rozwiązany lub odrzucony. To jest to samo, co użycie.done()
lub.fail()
.W jakiś sposób użyłbyś
.pipe()
(wstępnego) przefiltrowania wyniku. Wartość zwracana wywołania zwrotnego do.pipe()
zostanie przekazana jako argument do funkcjidone
i funkcjifail
zwrotnej. Może również zwrócić inny obiekt odroczony, a następujące wywołania zwrotne zostaną zarejestrowane w tym odroczonym.Tak nie jest w przypadku
.then()
(lub.done()
,.fail()
), wartości zwracane przez zarejestrowane wywołania zwrotne są po prostu ignorowane.Więc to nie jest tak, że używasz albo
.then()
lub.pipe()
. Państwo mogli korzystać.pipe()
z tych samych celów, co.then()
jednak rozmawiać nie trzyma.Przykład 1
Wynikiem jakiejś operacji jest tablica obiektów:
i chcesz obliczyć minimalną i maksymalną wartość. Załóżmy, że używamy dwóch
done
wywołań zwrotnych:W obu przypadkach musisz powtórzyć listę i wyodrębnić wartość z każdego obiektu.
Czy nie byłoby lepiej wcześniej jakoś wyodrębnić wartości, aby nie trzeba było tego robić osobno w obu wywołaniach zwrotnych? Tak! I to właśnie możemy wykorzystać
.pipe()
do:Oczywiście jest to zmyślony przykład i istnieje wiele różnych (być może lepszych) sposobów rozwiązania tego problemu, ale mam nadzieję, że ilustruje to.
Przykład 2
Rozważ połączenia Ajax. Czasami chcesz zainicjować jedno wywołanie Ajax po zakończeniu poprzedniego. Jednym ze sposobów jest wykonanie drugiego połączenia w
done
wywołaniu zwrotnym:Teraz załóżmy, że chcesz oddzielić kod i umieścić te dwa wywołania Ajax wewnątrz funkcji:
Chciałbyś użyć obiektu odroczonego, aby zezwolić na inny kod, który wywołuje
makeCalls
dołączenie wywołań zwrotnych dla drugiego wywołania Ajax, alenie przyniesie pożądanego efektu, ponieważ drugie wywołanie jest wykonywane wewnątrz
done
wywołania zwrotnego i nie jest dostępne z zewnątrz.Rozwiązaniem byłoby użycie
.pipe()
zamiast tego:Używając
.pipe()
możesz teraz umożliwić dołączanie wywołań zwrotnych do „wewnętrznego” wywołania Ajax bez ujawniania rzeczywistego przepływu / kolejności wywołań.Ogólnie rzecz biorąc, odroczone obiekty stanowią interesujący sposób na oddzielenie kodu :)
źródło
pipe
można filtrować,then
czego nie można. Ale wydaje się, że przy wyszukiwaniu w Google tych tematów zdecydowali się nazywać to,pipe
a niefilter
dlatego, że uważali filtrowanie za coś w rodzaju dodatkowego bonusu, który mu towarzyszył, podczas gdypipe
wyraźniej wskazywało na jego prawdziwy cel. Wygląda więc na to, że oprócz filtrowania powinny istnieć inne różnice. (Z drugiej strony przyznaję, że nie rozumiem funkcji filtrowania nawet z twoimi przykładami. Aresult values;
takreturn values;
przy okazji?).then()
otrzymują te same dane, wresult
których za każdym razem filtrujesz; podczas gdy w niższym przykładzie.pipe()
usuwa niektóre dane w swoimresult
przed przekazaniem ich dalej, gdyresult
dwa kolejne.then()
otrzymają?.pipe()
. Jeśli wywołanie zwrotne zwróci obiekt odroczony, kolejne wykonane lub zakończone niepowodzeniem wywołania zwrotne zostaną zarejestrowane dla tego obiektu. Podam inny przykład. edycja: jeśli chodzi o twój drugi komentarz: tak.pipe()
gdythen()
bardziej przypomina węzeł liścia, na końcu którego musisz użyć swoich danych i nie płynie dalej, i że pomimo faktu, żethen()
zwraca a,Deferred
nie jest faktycznie używany / przydatny? Jeśli to prawda, pomocne może być wyjaśnienie umieszczenia czegoś podobnego/* do something with "min"/"max" */
w każdej klauzuli „.then ()”.Nie ma przypadku, w którym MUSISZ użyć
then()
ponadpipe()
. Zawsze możesz zignorować wartość, którapipe()
zostanie przekazana. Używanie może spowodować niewielki spadek wydajnościpipe
- ale jest to mało prawdopodobne.Więc może się wydawać, że możesz po prostu zawsze używać
pipe()
w obu przypadkach. Jednakże , za pomocąpipe()
, komunikujesz się z innymi ludźmi czytania kodu (w tym siebie, sześć miesięcy od teraz), że istnieją pewne znaczenie dla wartości zwracanej. Jeśli go odrzucasz, naruszasz tę semantyczną konstrukcję.To tak, jakby mieć funkcję, która zwraca wartość, która nigdy nie jest używana: myląca.
Więc używaj
then()
kiedy powinieneś ipipe()
kiedy powinieneś ...źródło
$(function () { $.when(getPosition()) .pipe(lookupCountry) .then(displayResults); });
„Zauważ, że potok różni się od to dlatego, że fajka daje nową obietnicę ”.W rzeczywistości okazuje się, że różnica między
.then()
i.pipe()
została uznana za niepotrzebną i zostały one wykonane tak, aby były takie same jak w wersji jQuery 1.8.Z komentarza
jaubourg
w zgłoszeniu do śledzenia błędów jQuery # 11010 „MAKE DEFERRED.THEN == DEFERRED.PIPE LIKE PROMISE / A”:(emphassis mine)
źródło