Przeczytałem kilka artykułów na ten temat, ale nadal nie jest dla mnie jasne, czy istnieje różnica między Promise.reject
zgłaszaniem błędu. Na przykład,
Korzystanie z Promise.reject
return asyncIsPermitted()
.then(function(result) {
if (result === true) {
return true;
}
else {
return Promise.reject(new PermissionDenied());
}
});
Za pomocą rzutu
return asyncIsPermitted()
.then(function(result) {
if (result === true) {
return true;
}
else {
throw new PermissionDenied();
}
});
Wolę używać throw
po prostu dlatego, że jest krótszy, ale zastanawiałem się, czy jest jakaś przewaga jednego nad drugim.
javascript
promise
Naresh
źródło
źródło
.then()
przechwytuje zgłoszony wyjątek i automatycznie zamienia go w odrzuconą obietnicę. Ponieważ przeczytałem, że zgłoszone wyjątki nie są szczególnie szybkie do wykonania, zgaduję, że zwrócenie odrzuconej obietnicy może być nieco szybsze do wykonania, ale trzeba by było opracować test w wielu nowoczesnych przeglądarkach, gdyby to było ważne. Osobiście używam,throw
ponieważ lubię czytelność.throw
jest to, że nie spowodowałoby to odrzucenia obietnicy, gdyby została wyrzucona z asynchronicznego wywołania zwrotnego, takiego jak setTimeout. jsfiddle.net/m07van33 @Blondie Twoja odpowiedź była poprawna.reject
go na liście parametrów.Odpowiedzi:
Nie ma żadnej korzyści z używania jednego kontra drugiego, ale istnieje konkretny przypadek, w którym
throw
nie zadziała. Te przypadki można jednak naprawić.Za każdym razem, gdy znajdziesz się w ramach oddzwaniania od obietnicy, możesz z niego skorzystać
throw
. Jeśli jednak korzystasz z innego asynchronicznego połączenia zwrotnego, musisz go użyćreject
.Na przykład nie spowoduje to wyłapania:
Zamiast tego masz nierozwiązaną obietnicę i niewykorzystany wyjątek. Jest to przypadek, w którym chciałbyś zamiast tego użyć
reject
. Można to jednak naprawić na dwa sposoby.źródło
throw error
, nie możesz również użyć, oreturn Promise.reject(err)
co OP poprosił nas o porównanie. Zasadniczo dlatego nie należy umieszczać wywołań asynchronicznych w obietnicach. Promuj wszystko, co asynchronizuje, a wtedy nie masz tych ograniczeń.Array#forEach
) i z tymi, rzucanie w nich działałoby.throw
nie będą działać, a zamiast tegoPromise.reject
są lepszym wyborem. Jednak na fragmenty nie ma wpływu żadna z tych dwóch opcji i dają taki sam wynik niezależnie od tego, co wybierzesz. Czy coś brakuje?reject
co zostało przekazane donew Promise(fn)
oddzwaniania.return Promise.reject()
ithrow
. Nie wspomina oreject
wywołaniu zwrotnym podanym wnew Promise(function(resolve, reject))
konstrukcji. Więc chociaż twoje dwa fragmenty słusznie pokazują, kiedy powinieneś użyć wywołania zwrotnego rozstrzygania, pytanie OP nie było takie.Innym ważnym faktem jest to, że
reject()
NIE przerywa przepływu sterowania, jakreturn
robi to instrukcja. W przeciwieństwie dothrow
tego kończy sterowanie przepływem.Przykład:
vs
źródło
return reject()
, więc następny wiersz się nie uruchomi.return reject()
jest to po prostu skrót,reject(); return
tzn. To, czego chcesz, to zakończyć przepływ. Zwracana wartość modułu wykonującego (funkcja przekazana donew Promise
) nie jest używana, więc jest to bezpieczne.Tak, największą różnicą jest to, że odrzucenie to funkcja zwrotna, która jest wykonywana po odrzuceniu obietnicy, podczas gdy rzut nie może być użyty asynchronicznie. Jeśli zdecydujesz się użyć odrzucenia, twój kod będzie nadal działał normalnie w sposób asynchroniczny, podczas gdy rzut będzie priorytetem dla ukończenia funkcji resolvera (ta funkcja uruchomi się natychmiast).
Przykład, który widziałem, który pomógł mi wyjaśnić ten problem, to to, że możesz ustawić funkcję Limit czasu z odrzuceniem, na przykład:
Powyższe nie byłoby możliwe do napisania rzutem.
W twoim małym przykładzie różnica w nierozróżnialnym, ale w przypadku bardziej skomplikowanej koncepcji asynchronicznej różnica między nimi może być drastyczna.
źródło
TLDR: Funkcja jest trudna w użyciu, gdy czasami zwraca obietnicę, a czasem zgłasza wyjątek. Pisząc funkcję asynchroniczną, wolisz zasygnalizować błąd, zwracając odrzuconą obietnicę
Twój konkretny przykład zaciemnia niektóre ważne różnice między nimi:
Ponieważ zajmujesz się błędami w łańcuchu obietnic, zgłoszone wyjątki są automatycznie konwertowane na odrzucone obietnice. To może wyjaśniać, dlaczego wydają się one wymienne - nie są.
Rozważ poniższą sytuację:
Byłby to anty-wzorzec, ponieważ musiałbyś wtedy obsługiwać zarówno przypadki błędów asynchronizacji, jak i synchronizacji. Może wyglądać mniej więcej tak:
Nie jest dobrze, a oto gdzie dokładnie
Promise.reject
(dostępny w skali globalnej) przychodzi na ratunek i skutecznie się odróżniathrow
. Refaktor staje się teraz:To pozwala teraz używać tylko jednego w
catch()
przypadku awarii sieci i synchronicznego sprawdzania błędów pod kątem braku tokenów:źródło
Promise.reject
lubthrow
kiedy chcesz zwrócić odrzuconą obietnicę (obietnicę, która przejdzie do następnej.catch()
).checkCredentials(x).then(onFulfilled).catch(e) {}
, aby posiadałcatch
zarówno przypadek odrzucenia, jak i przypadek błędu?Przykład do wypróbowania. Wystarczy zmienić isVersionThrow na false, aby użyć odrzucenia zamiast rzutu.
źródło