Przeszukiwałem async
/ await
i po przejrzeniu kilku artykułów postanowiłem sam przetestować. Jednak wydaje mi się, że nie mogę zrozumieć, dlaczego to nie działa:
async function main() {
var value = await Promise.resolve('Hey there');
console.log('inside: ' + value);
return value;
}
var text = main();
console.log('outside: ' + text);
Konsola wyświetla następujące informacje (węzeł v8.6.0):
> na zewnątrz: [obietnica obiektu]
> wewnątrz: Hej
Dlaczego komunikat dziennika wewnątrz funkcji jest później wykonywany? Myślałem, że powodem async
/ await
został utworzony w celu wykonania synchronicznego wykonywania przy użyciu zadań asynchronicznych.
Czy istnieje sposób, aby użyć wartości zwróconej w funkcji bez użycia .then()
after main()
?
await
to nic innego jak cukier dlathen
składni obietnicy .main
async/await
jest częścią ES2017, a nie ES7 (ES2016)Odpowiedzi:
Ponieważ
main
zwraca obietnicę; wszystkieasync
funkcje robią.Na najwyższym poziomie musisz:
Użyj funkcji najwyższego poziomu,
async
która nigdy nie odrzuca (chyba że chcesz uzyskać błędy „nieobsługiwanego odrzucenia”) lubUżyj
then
icatch
, lub(Wkrótce!) Użyj najwyższego poziomu
await
, propozycji, która osiągnęła etap 3 w procesie, który pozwala na użycie najwyższego poziomuawait
w module.# 1 -
async
Funkcja najwyższego poziomu, która nigdy nie odrzucaZwróć uwagę na
catch
; Państwo musi obsługiwać odrzucenia obietnica / async wyjątki, gdyż nic innego nie będzie; nie masz rozmówcy, któremu mógłbyś je przekazać. Jeśli wolisz, możesz to zrobić na wyniku wywołania go za pomocącatch
funkcji (zamiasttry
/catch
syntax):... który jest nieco bardziej zwięzły (podoba mi się z tego powodu).
Lub, oczywiście, nie obsługuj błędów i po prostu zezwalaj na błąd „nieobsługiwanego odrzucenia”.
# 2 -
then
icatch
Procedura
catch
obsługi zostanie wywołana, jeśli wystąpią błędy w łańcuchu lub w twoimthen
module obsługi. (Upewnij się, żecatch
program obsługi nie zgłasza błędów, ponieważ nic nie zostało zarejestrowane do ich obsługi).Lub oba argumenty za
then
:Ponownie zauważ, że rejestrujemy moduł obsługi odrzucania. Ale w tej formie upewnij się, że żaden z twoich plików
then
wywołań zwrotnych nie generuje żadnych błędów, nic nie jest zarejestrowane, aby je obsłużyć.# 3 najwyższy poziom
await
w moduleNie można używać
await
na najwyższym poziomie skryptu niebędącego modułem, ale propozycja najwyższego poziomuawait
( Etap 3 ) pozwala na użycie go na najwyższym poziomie modułu. Jest to podobne do używaniaasync
opakowania funkcji najwyższego poziomu (# 1 powyżej), ponieważ nie chcesz, aby kod najwyższego poziomu odrzucał (zgłaszał błąd), ponieważ spowoduje to nieobsłużony błąd odrzucenia. Więc jeśli nie chcesz mieć tego nieobsługiwanego odrzucenia, gdy coś pójdzie nie tak, jak w przypadku # 1, chciałbyś opakować swój kod w moduł obsługi błędów:Zwróć uwagę, że jeśli to zrobisz, każdy moduł, który zaimportuje z Twojego modułu, będzie czekał, aż obietnica, którą tworzysz, zostanie
await
spełniona; kiedy moduł używający najwyższego poziomuawait
jest oceniany, w zasadzie zwraca obietnicę do modułu ładującego (podobnie jakasync
funkcja), który czeka, aż ta obietnica zostanie rozliczona, przed oceną treści wszelkich modułów, które od niej zależą.źródło
async
/await
są cukrem syntaktycznym wokół obietnic (dobry rodzaj cukru :-)). Nie myślisz o tym tylko jako o zwrocie obietnicy; faktycznie tak. ( Szczegóły )async
opcją all- first. W przypadku funkcji najwyższego poziomu widzę to tak czy inaczej (głównie z powodu dwóch poziomów wcięć wasync
wersji).await
propozycja najwyższego poziomu osiągnęła etap 3. :-)Najwyższy poziom
await
przeszedł do etapu 3, więc odpowiedź na Twoje pytanie Jak mogę używać async / await na najwyższym poziomie? to po prostu dodaćawait
wywołanie domain()
:Lub tylko:
Pamiętaj, że nadal jest dostępny tylko w [email protected] .
Jeśli używasz TypeScript , wylądował w 3.8 .
v8 dodał wsparcie w modułach.
Jest również obsługiwany przez Deno (jak skomentował gonzalo-bahamondez).
źródło
Rzeczywistym rozwiązaniem tego problemu jest podejście do tego inaczej.
Prawdopodobnie Twoim celem jest jakaś inicjalizacja, która zwykle ma miejsce na najwyższym poziomie aplikacji.
Rozwiązaniem jest zapewnienie, że na najwyższym poziomie aplikacji istnieje tylko jedna instrukcja JavaScript. Jeśli masz tylko jedną instrukcję u góry aplikacji, możesz swobodnie używać async / await w każdym innym miejscu (oczywiście z zastrzeżeniem normalnych reguł składni)
Innymi słowy, zawiń cały najwyższy poziom w funkcję, aby nie był już najwyższym poziomem i to rozwiązuje pytanie, jak uruchomić async / await na najwyższym poziomie aplikacji - tego nie robisz.
Tak powinien wyglądać najwyższy poziom Twojej aplikacji:
źródło
application()
był asynchroniczny?Aby podać dodatkowe informacje na temat aktualnych odpowiedzi:
Zawartość pliku
node.js
pliku jest obecnie łączona w sposób podobny do łańcucha, aby utworzyć funkcji.Na przykład, jeśli masz plik
test.js
:Następnie
node.js
potajemnie połączy funkcję, która wygląda następująco:Najważniejszą rzeczą, na którą należy zwrócić uwagę, jest to, że wynikowa funkcja NIE jest funkcją asynchroniczną. Nie możesz więc użyć tego terminu
await
bezpośrednio w nim!Ale powiedz, że musisz pracować z obietnicami w tym pliku, istnieją dwie możliwe metody:
await
bezpośrednio w funkcjiawait
Opcja 1 wymaga od nas stworzenia nowego zakresu (a TEN zakres może być
async
, ponieważ mamy nad nim kontrolę):Opcja 2 wymaga od nas użycia zorientowanego obiektowo interfejsu API obietnic (mniej ładny, ale równie funkcjonalny paradygmat pracy z obietnicami)
Osobiście mam nadzieję, że jeśli będzie to wykonalne, node.js domyślnie połączy kod w
async
funkcję. To by pozbyło się tego bólu głowy.źródło
Oczekiwanie na najwyższym poziomie to funkcja nadchodzącego standardu EcmaScript. Obecnie możesz zacząć używać go z TypeScript 3.8 (obecnie w wersji RC).
Jak zainstalować TypeScript 3.8
Możesz rozpocząć korzystanie z TypeScript 3.8, instalując go z npm za pomocą następującego polecenia:
W tej chwili musisz dodać
rc
tag, aby zainstalować najnowszą wersję 3.8 maszynopisu.źródło
Ponieważ
main()
działa asynchronicznie, zwraca obietnicę. Wynik musisz uzyskaćthen()
metodą. A ponieważthen()
zwroty też obiecują, musisz zadzwonić,process.exit()
aby zakończyć program.źródło
exit()
aby zasygnalizować, czy wystąpił błąd.process.exit(1)