Как работают Promise и async/await?

MiddleJavaScript #javascript #async #promises

Вопрос

Что такое Promise и как соотносится с ним async/await?

Короткий ответ

Promise — это объект, представляющий результат асинхронной операции в одном из трёх состояний: pending, fulfilled или rejected. async/await — синтаксический сахар над промисами, позволяющий писать асинхронный код в синхронном стиле.

Подробный ответ

Промис создаётся с executor-функцией, которая вызывает resolve или reject:

new Promise((resolve, reject) => {
  // ...
})

Состояние промиса меняется только один раз и необратимо. Методы .then()/.catch()/.finally() регистрируют обработчики, которые выполнятся как микрозадачи.

async function всегда возвращает промис. await приостанавливает выполнение функции до разрешения промиса, не блокируя основной поток — под капотом это тоже работа с микрозадачами.

Полезные статические методы:

  • Promise.all — ждёт все промисы, падает при первой ошибке.
  • Promise.allSettled — ждёт все, не падает, возвращает статус каждого.
  • Promise.race — резолвится/реджектится по первому завершившемуся промису.

Пример

async function loadUser(id) {
  try {
    const response = await fetch(`/api/users/${id}`)
    if (!response.ok) throw new Error('Не удалось загрузить')
    return await response.json()
  } catch (error) {
    console.error(error)
    throw error
  }
}

// Параллельное выполнение вместо последовательного await
const [user, posts] = await Promise.all([
  loadUser(1),
  fetch('/api/posts').then(r => r.json())
])

Дополнительные вопросы

  • В чём разница между Promise.all и Promise.allSettled?
  • Что произойдёт, если не обработать rejected-промис?
  • Почему последовательные await в цикле медленнее, чем Promise.all?

Связанные вопросы