async/await vs then()
async/await pozwala pisać kod asynchroniczny jak zwykły, sekwencyjny, z błędami w try...catch, a then() tworzy łańcuch wywołań na samej obietnicy.
Porównanie w tabeli
#Jak zapisujesz kolejne kroki
- async function
- Jak zwykły kod, linia po linii z
await - Promise.prototype.then()
- Jako łańcuch wywołań
.then()
Obsługa błędów
- async function
- Blok
try...catch - Promise.prototype.then()
- Metoda
.catch()na końcu łańcucha
Co zwraca wywołanie funkcji
- async function
- Zawsze
Promise, nawet dla zwykłegoreturn - Promise.prototype.then()
- Zawsze nową
Promise, inną przy każdym.then()
Najczęstszy błąd
- async function
- Zapomniany
awaitprzed wywołaniem - Promise.prototype.then()
- Zapomniany
returnw środku łańcucha
Równoległe operacje
- async function
await Promise.all([...])- Promise.prototype.then()
Promise.all([...]).then(...)
Typowe użycie
- async function
- Wiele kroków, warunki, pętle z oczekiwaniem
- Promise.prototype.then()
- Jeden krok albo krótki łańcuch bez
async
Przykład
#const wait = (ms, value) => new Promise((resolve) => setTimeout(() => resolve(value), ms))
async function loadWithAwait() {
const points = await wait(100, 120)
return points + 10
}
function loadWithThen() {
return wait(100, 120).then((points) => points + 10)
}
console.log(await loadWithAwait())
console.log(await loadWithThen())Definicja i zastosowanie
#To dwa sposoby pracy z tym samym mechanizmem obietnic, nie dwie różne technologie. Funkcja async zawsze zwraca Promise, tak jak zawsze robi to then(). Wewnątrz funkcji async operator await wstrzymuje wykonanie do rozstrzygnięcia obietnicy, a then() rejestruje funkcję, która zostanie wywołana z jej wynikiem.
Różnica jest w zapisie i obsłudze błędów. Z await kod wygląda jak zwykłe, sekwencyjne instrukcje, a błędy łapiesz znanym blokiem try...catch. then() wymaga łańcucha wywołań, w którym każdy krok musi zwrócić wartość albo obietnicę, a błędy obsługuje catch() na końcu. Zapomniany return w środku łańcucha then() to częsty błąd: następny krok dostaje undefined i nie czeka na wynik poprzedniego.
Do wielu kroków, warunków i pętli z oczekiwaniem używaj async/await, bo taki kod łatwiej czytać i debugować. Krótka, jednorazowa obietnica albo funkcja pomocnicza, która ma zostać zwykłą (nie async) funkcją, może zostać przy then() i catch().
Składnia
#async function name() {
const value = await promise
return value
}
promise.then((value) => value).catch((error) => {})Więcej przykładów
#const fail = (ms, message) =>
new Promise((_, reject) => setTimeout(() => reject(new Error(message)), ms))
async function withAwait() {
try {
await fail(100, 'Sesja wygasła')
} catch (error) {
console.log('await:', error.message)
}
}
function withThen() {
return fail(100, 'Sesja wygasła').catch((error) => console.log('then:', error.message))
}
await withAwait()
await withThen()const wait = (ms, value) => new Promise((resolve) => setTimeout(() => resolve(value), ms))
function chainWithBug() {
return wait(100, 'Lekcja 1').then((lesson) => {
wait(100, lesson + ' ukończona')
})
}
async function sequenceFixed() {
const lesson = await wait(100, 'Lekcja 1')
return await wait(100, lesson + ' ukończona')
}
console.log(await chainWithBug())
console.log(await sequenceFixed())W chainWithBug() funkcja w then() nie ma return, więc łańcuch nie czeka na wewnętrzną obietnicę i dostaje undefined. Z await taki błąd nie ma szansy się zdarzyć, bo kolejny krok zawsze czeka na poprzedni.
Dobre praktyki
#- W nowym kodzie z wieloma krokami sięgaj po
async/await. Czyta się jak zwykły kod wykonywany z góry na dół. - Pisząc
.then(), pamiętaj oreturnw każdym kroku łańcucha. Bez niego następny krok nie czeka na wewnętrzną obietnicę. - Wewnątrz funkcji
asyncobsłuż błędy blokiemtry...catch. Przy zwykłym łańcuchu użyj jednegocatch()na jego końcu.
Powiązane hasła
#- async functionDeklaruje funkcję asynchroniczną, która zawsze zwraca obietnicę i może używać w środku słowa await.
- Promise.prototype.then()Rejestruje funkcję wywoływaną po spełnieniu obietnicy i zwraca nową obietnicę, co pozwala łączyć kroki w łańcuch.
- awaitWstrzymuje funkcję async do czasu rozstrzygnięcia obietnicy i zwraca jej wartość albo rzuca jej błąd.
- Promise.prototype.catch()Rejestruje funkcję obsługi błędu, wywoływaną, gdy obietnica zostanie odrzucona.
Widzisz błąd albo brakuje przykładu? Napisz do nas.