Rzuciłem okiem na często zadawane pytania dotyczące obietnicy bluebird , w których wspomina, że .then(success, fail)
jest to antypattern . Nie do końca rozumiem jego wyjaśnienie dotyczące próby złapania. Co jest z tym nie tak?
some_promise_call()
.then(function(res) { logger.log(res) }, function(err) { logger.log(err) })
Wygląda na to, że przykład sugeruje następujące postępowanie jako prawidłowy sposób.
some_promise_call()
.then(function(res) { logger.log(res) })
.catch(function(err) { logger.log(err) })
Co za różnica?
javascript
node.js
promise
bluebird
użytkownik2127480
źródło
źródło
then().catch()
jest bardziej czytelny, ponieważ nie musisz szukać przecinka i sprawdzać, czy jest to wywołanie zwrotne dla gałęzi sukcesu lub niepowodzenia..catch
, nie wiesz, który krok spowodował problem - w ostatnimthen
lub gdzieś w górę łańcucha obietnic. Ma to więc swoją własną wadę.some_promise_call() .then(function fulfilled(res) { logger.log(res) }, function rejected(err) { logger.log(err) })
Odpowiedzi:
.then()
Rozmowa powróci obietnicę, że zostanie odrzucona w przypadku oddzwaniania zgłasza błąd. Oznacza to, że gdy Twój sukces sięlogger
nie powiedzie, błąd zostanie przekazany do następującego.catch()
wywołania zwrotnego, ale nie dofail
wywołania zwrotnego, które towarzyszysuccess
.Oto schemat kontrolny :
Aby wyrazić to w kodzie synchronicznym:
Drugi
log
(który jest jak pierwszy argument.then()
) zostanie wykonany tylko w przypadku, gdy nie wystąpi żaden wyjątek. Znakowany blok ibreak
oświadczenie czujesz się trochę dziwne, to jest rzeczywiście to, co python matry-except-else
dla (zalecane lektury!).Program
catch
rejestrujący będzie także obsługiwał wyjątki od wywołania programu rejestrującego sukces.Tyle o różnicy.
Argument jest taki, że zwykle chcesz wychwytywać błędy na każdym etapie przetwarzania i że nie powinieneś używać go w łańcuchach. Oczekuje się, że masz tylko jeden końcowy moduł obsługi, który obsługuje wszystkie błędy - podczas gdy podczas korzystania z „antipattern” błędy w niektórych wywołaniach zwrotnych nie są obsługiwane.
Jednak ten wzorzec jest w rzeczywistości bardzo przydatny: gdy chcesz obsłużyć błędy, które wystąpiły dokładnie w tym kroku, i chcesz zrobić coś zupełnie innego, gdy nie wystąpił błąd - tj. Gdy błąd jest nie do naprawienia. Pamiętaj, że to rozgałęzia twój przepływ kontroli. Oczywiście jest to czasem pożądane.
Że musisz powtórzyć oddzwonienie. Raczej chcesz
Możesz również rozważyć użycie
.finally()
do tego celu.źródło
.catch
będą wychwytywać błędy nawet w funkcji sukcesu . Osobiście uważam to za bardzo błędne, ponieważ kończysz z jednym punktem wejścia błędu, który może uzyskać wiele błędów z wiele działań, ale to mój problem. W każdym razie - dzięki za informację! Czy nie masz narzędzia komunikacji online, które chcesz udostępnić, abym mógł prosić o kilka rzeczy więcej? : PPromise
mechanika na tej stronie..done()
nie jest częścią standardu, prawda? Przynajmniej MDN nie podaje tej metody. To było by pomocne.done
jest rzeczą Bluebird, która została zasadniczo przestarzała przezthen
+ wykrywanie nieobsługiwanego odrzucenia.Te dwa nie są do końca identyczne. Różnica polega na tym, że pierwszy przykład nie złapie wyjątku zgłoszonego w
success
module obsługi. Tak więc, jeśli twoja metoda powinna zwracać tylko rozwiązane obietnice, jak to często bywa, potrzebujesz końcowejcatch
procedury obsługi (lub jeszcze innejthen
z pustymsuccess
parametrem). Jasne, może się zdarzyć, że twójthen
program obsługi nie zrobi niczego, co mogłoby potencjalnie zawieść, w takim przypadku użycie jednego 2-parametruthen
może być w porządku.Uważam jednak, że sens tekstu, do którego się odnosisz,
then
jest najbardziej przydatny w porównaniu do wywołań zwrotnych w jego zdolności do łączenia szeregu asynchronicznych kroków, a kiedy faktycznie to robisz, 2-parametrowa formathen
subtelnie nie zachowuje się tak, jak się spodziewano , z powyższego powodu. Jest to szczególnie sprzeczne z intuicją, gdy jest używane w połowie łańcucha.Jako ktoś, kto wykonał wiele skomplikowanych zadań asynchronicznych i wpadł na takie zakręty bardziej, niż się to przyznaję, naprawdę zalecam unikanie tego anty-wzorca i stosowanie osobnego podejścia obsługi.
źródło
Patrząc na zalety i wady obu tych elementów, możemy wyliczyć, które z nich jest odpowiednie w danej sytuacji. Są to dwa główne podejścia do realizacji obietnic. Oba mają swoje plusy i minusy
Zalety
Niedogodności
Zalety
Wady
catch
jeśli chcesz obsługiwać błędy generowane przez wywołanie zwrotne sukcesuźródło
Proste wyjaśnienie:
W ES2018
to znaczy:
równa się
źródło
Użycie
.then().catch()
pozwala włączyć Łańcuch obietnicy, który jest wymagany do realizacji przepływu pracy. Może być konieczne odczytanie niektórych informacji z bazy danych, a następnie przekazanie ich do asynchronicznego interfejsu API, a następnie manipulowanie odpowiedzią. Możesz zepchnąć odpowiedź z powrotem do bazy danych. Obsługa wszystkich tych przepływów pracy za pomocą koncepcji jest wykonalna, ale bardzo trudna do zarządzania. Lepszym rozwiązaniem będziethen().then().then().then().catch()
otrzymywanie wszystkich błędów za jednym razem catch i pozwala zachować łatwość konserwacji kodu.źródło
Korzystanie
then()
icatch()
pomoc w łańcuchu obsługi sukcesu i niepowodzenia w obietnicy.catch()
działa na podstawie obietnicy zwróconej przezthen()
. Radzi sobie,then()
tego nie obsługuje).1. let promiseRef: Promise = this. aTimetakingTask (false); 2. promiseRef 3. .then( 4. (result) => { 5. /* successfully, resolved promise. 6. Work on data here */ 7. }, 8. (error) => console.log(error) 9. ) 10. .catch( (e) => { 11. /* successfully, resolved promise. 12. Work on data here */ 13. });
Ma to sens, ponieważ zwrócona przez
then()
nie obietnica nie zawiera błędu, jeśli zajmuje się nią wywołanie zwrotne.źródło
catch
wywołania zwrotnego wydaje się nieprawidłowa.Zamiast słów dobry przykład. Poniższy kod (jeśli pierwsza obietnica została rozwiązana):
jest identyczny z:
Ale przy odrzuconej pierwszej obietnicy nie jest to identyczne:
źródło