PorównaniePorównania

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.

Na tej stronie

Porównanie w tabeli

#

Przykład

#
JavaScript
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())
Konsola
130
130

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

#
Składnia
async function name() {
  const value = await promise
  return value
}

promise.then((value) => value).catch((error) => {})

Więcej przykładów

#
Obsługa błędu: try...catch kontra catch()
JavaScript
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()
Konsola
await: Sesja wygasła
then: Sesja wygasła
Pułapka: zapomniany return w then()
JavaScript
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())
Konsola
undefined
Lekcja 1 ukończona

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 o return w każdym kroku łańcucha. Bez niego następny krok nie czeka na wewnętrzną obietnicę.
  • Wewnątrz funkcji async obsłuż błędy blokiem try...catch. Przy zwykłym łańcuchu użyj jednego catch() na jego końcu.

Powiązane hasła

#

Widzisz błąd albo brakuje przykładu? Napisz do nas.