O ile rozumiem, w ES7 / ES2016 umieszczanie wielu await
w kodzie będzie działać podobnie do łączenia łańcuchowego .then()
z obietnicami, co oznacza, że będą one wykonywać jeden po drugim, a nie równolegle. Na przykład mamy ten kod:
await someCall();
await anotherCall();
Czy rozumiem to poprawnie, że anotherCall()
zostanie wywołane dopiero po someCall()
zakończeniu? Jaki jest najbardziej elegancki sposób nazywania ich równolegle?
Chcę go używać w węźle, więc może istnieje rozwiązanie z biblioteką asynchroniczną?
EDYCJA: Nie jestem zadowolony z rozwiązania przedstawionego w tym pytaniu: Spowolnienie z powodu nierównoległego oczekiwania na obietnice w generatorach asynchronicznych , ponieważ używa generatorów i pytam o bardziej ogólny przypadek użycia.
javascript
node.js
asynchronous
ecmascript-6
babeljs
Victor Marchuk
źródło
źródło
await
czekałaby na zakończenie pierwszej funkcji całkowicie przed wykonaniem drugiego.Promise
s. Połączone pytanie dotyczy biblioteki bluebird z generatorami i wydajnością. Być może podobne koncepcyjnie, ale nie w realizacji.Odpowiedzi:
Możesz poczekać na
Promise.all()
:Aby zapisać wyniki:
Zauważ, że
Promise.all
szybko się nie udaje, co oznacza, że gdy tylko jedna z podanych mu obietnic odrzuci, wtedy cała rzecz odrzuci.Jeśli zamiast tego chcesz poczekać na spełnienie lub odrzucenie wszystkich obietnic, możesz skorzystać
Promise.allSettled
. Zauważ, że Internet Explorer nie obsługuje natywnie tej metody.źródło
[result1, result2] = Promise.all([async1(), async2()]);
= await Promise.all
?TL; DR
Użyj
Promise.all
dla równoległych wywołań funkcji, zachowanie nie odpowiada poprawnie, gdy wystąpi błąd.Najpierw wykonaj wszystkie asynchroniczne wywołania jednocześnie i uzyskaj wszystkie
Promise
obiekty. Po drugie, użyjawait
naPromise
obiektach. W ten sposób podczas oczekiwania naPromise
rozstrzygnięcie pozostałych asynchronicznych wywołań nadal postępuje. Ogólnie rzecz biorąc, będziesz czekać tylko tak długo, jak najwolniejsze połączenie asynchroniczne. Na przykład:Przykład JSbin: http://jsbin.com/xerifanima/edit?js,console
Zastrzeżenie: Nie ma znaczenia, czy
await
połączenia są na tej samej linii, czy na różnych liniach, o ile pierwszeawait
połączenie następuje po wszystkich połączeniach asynchronicznych. Zobacz komentarz JohnnyHK.Aktualizacja: ta odpowiedź ma inny czas obsługi błędów w zależności od odpowiedzi @ bergi , NIE wyrzuca błędu w momencie wystąpienia błędu, ale po wykonaniu wszystkich obietnic. Porównuję wynik z wskazówką @ jonny:
[result1, result2] = Promise.all([async1(), async2()])
sprawdź następujący fragment koduźródło
[someResult, anotherResult] = [await someResult, await anotherResult]
jeśli zmieniconst
sięlet
.await
polecenia serio, prawda? Oznacza to, że wykonywanie jest wstrzymywane do momentu pierwszegoawait
rozstrzygnięcia, a następnie przechodzi do drugiego.Promise.all
wykonuje się równolegle.Promise.all
. Jeśli każde żądanie jest połączeniem sieciowym,await someResult
należy je rozwiązać, zanimawait anotherResult
jeszcze zostanie uruchomione. I odwrotnie, wPromise.all
obuawait
połączeniach można rozpocząć przed rozstrzygnięciem jednego z nich.Aktualizacja:
Oryginalna odpowiedź utrudnia (a w niektórych przypadkach uniemożliwia) prawidłową obsługę odrzuconych obietnic. Prawidłowym rozwiązaniem jest użycie
Promise.all
:Oryginalna odpowiedź:
Upewnij się tylko, że wywołujesz obie funkcje, zanim zaczekasz na jedną z nich:
źródło
await
następnie przekształcają je w rzeczywiste wartości.Istnieje inny sposób bez Promise.all (), aby zrobić to równolegle:
Po pierwsze, mamy 2 funkcje do drukowania liczb:
To jest sekwencyjne:
Jest to równoległe:
źródło
Można to osiągnąć za pomocą Promise.allSettled () , która jest podobna do
Promise.all()
zachowania bezawaryjnego, ale bez niego.Uwaga : jest to najnowocześniejsza funkcja z ograniczoną obsługą przeglądarki, dlatego zdecydowanie zalecam dodanie do tej funkcji polifill.
źródło
Stworzyłem istotę testującą różne sposoby rozwiązywania obietnic, z wynikami. Pomocne może być sprawdzenie działających opcji.
źródło
Chociaż ustawienie p1, p2 i p3 nie jest ściśle uruchamiane równolegle, nie wstrzymują one żadnego wykonania i można złapać błędy kontekstowe za pomocą haczyka.
źródło
W moim przypadku mam kilka zadań, które chcę wykonywać równolegle, ale muszę zrobić coś innego z wynikiem tych zadań.
A wynik:
źródło
czekaj na Promise.all ([someCall (), anotherCall ()]); jak już wspomniano, będzie działać jak ogrodzenie wątku (bardzo powszechne w kodzie równoległym jako CUDA), dlatego pozwoli na działanie wszystkich zawartych w nim obietnic bez wzajemnego blokowania, ale uniemożliwi kontynuowanie wykonywania, dopóki WSZYSTKIE nie zostaną rozwiązane.
innym podejściem, które warto udostępnić, jest asynchronizacja Node.js, która pozwoli również łatwo kontrolować ilość współbieżności, która jest zwykle pożądana, jeśli zadanie jest bezpośrednio powiązane z wykorzystaniem ograniczonych zasobów jako wywołania API, operacji we / wy, itp.
Podziękowania dla autora artykułu Medium ( czytaj więcej )
źródło
Głosuję za:
Pamiętaj o momencie, w którym wywołujesz funkcje, może to spowodować nieoczekiwany rezultat:
Ale przestrzeganie zawsze powoduje żądanie utworzenia nowego użytkownika
źródło
else
blokami.Tworzę funkcję pomocnika waitAll, może sprawi, że będzie słodsza. Na razie działa tylko w nodejs , a nie w przeglądarce Chrome.
źródło
for
Pętla kolejno czeka każdą obietnicę i dodaje wynik do tablicy.