Jeśli mam taki kod:
const async funkcja = () => {
const data = await getData()
}
const a = 'abc'
funkcja()
console.log(a)
To najpierw musi wykonać się akcja asynchroniczna z funkcji funkcja(), a potem dopiero się wykona console.log(a)?
Jeśli mam taki kod:
const async funkcja = () => {
const data = await getData()
}
const a = 'abc'
funkcja()
console.log(a)
To najpierw musi wykonać się akcja asynchroniczna z funkcji funkcja(), a potem dopiero się wykona console.log(a)?
Nie, wywołanie funkcja()
uruchamia tę asynchroniczną funkcję niejako "w tle", nie czekając na jej zakończenie - o czym możesz się przekonać dorzucając tam więcej console.log()
-ów lub uruchamiając kod pod debuggerem :-)
Istnieje możliwość wywołania await
poza funkcją.
Możesz sobie poczytać o top level await
, bo NodeJS obsługuje to od wersji > 14.8 jeśli się nie mylę, albo w przeglądarce jak oznaczymy skrypt jako type="module
.
<script type="module">
const topLevelAsync = () => {
return new Promise((resolve, reject) => {
console.log("najpierw console.log z promise'a");
resolve('koniec funkcji asynchronicznej');
});
}
const value = await topLevelAsync();
console.log(value);
console.log('koniec skryptu');
</script>
Gdy usuniemy z tego przykładu type="module"
to od razu dostajemy błąd Uncaught SyntaxError: await is only valid in async functions and the top level bodies of modules
.
Możesz też to opakować w jedną funkcje i użyć tego tak:
const a = 'abc';
const funkcja = async () => {
const data = await getData();
console.log(a);
}
funkcja();
Najpierw się uruchomi funkcja
. Jednak przy pierwszym await
zostanie jakby "zapauzowana", a reszta programu będzie się zachowywać tak, jakby funkcja została skończona czyli program idzie dalej (polecam zabawę obiektami Promise
, na których bazuje async/await, wtedy łatwiej może będzie zrozumieć ten mechanizm).
Ponieważ program idzie dalej, to włącza się console.log, który jest za wywołaniem funkcji, więc wypisuje abc
. Oraz jeśli masz jakieś inne linijki kodu dalej, to też wszystko się wykona.
I dopiero wtedy, kiedy się wszystko wykona, co ma się wykonać synchronicznie, to silnik JavaScriptu będzie patrzył, czy nie ma czegoś do odpalenia asynchronicznie.
I dopiero wtedy funkcja dostanie dane z await getData (zakładając, że te dane już są, tj. że dany Promise się rozwiązał)
Czyli jeśli będziemy mieć taki kod:
const getData = () => Promise.resolve('jakieś dane');
const funkcja = async () => {
console.log("uruchamiam funkcję");
const data = await getData();
console.log(data);
}
const a = 'abc'
funkcja()
console.log(a)
console.log("xD");
to dostaniemy na wyjściu:
uruchamiam funkcję
abc
xD
jakieś dane