Промисы

Объект-обещание, который распрямляет лесенку колбэков в читаемую цепочку.

Promise (промис) — это объект, представляющий результат асинхронной операции, который появится в будущем: либо успешно (resolved), либо с ошибкой (rejected).

Три состояния промиса

Промис всегда находится в одном из трёх состояний:

  • pending — ожидание, операция ещё идёт;
  • fulfilled — выполнен успешно, есть результат;
  • rejected — завершился ошибкой.

Из pending промис переходит в одно из конечных состояний ровно один раз и больше не меняется. Это важное свойство: если промис уже разрешился успехом, повторно «упасть» он не сможет, и наоборот. Поэтому промис безопасно передавать в разные части программы — каждый получит один и тот же финальный результат, а не запустит операцию заново.

then и catch

Результат успешного промиса забирают через .then, ошибку — через .catch:

const promise = new Promise((resolve, reject) => {
  const ok = true;
  if (ok) {
    resolve("успех");
  } else {
    reject("провал");
  }
});

promise
  .then((result) => console.log("Готово:", result))
  .catch((error) => console.log("Ошибка:", error));

Вывод:

Готово: успех

Цепочки вместо лесенки

Главное преимущество: .then можно выстраивать в цепочку. Если в .then вернуть новый промис, следующий .then дождётся его. Так зависимые операции выстраиваются ровно вниз, а не вправо:

function step(name, value) {
  return Promise.resolve(value).then((v) => {
    console.log(name, "->", v);
    return v + 1;
  });
}

step("шаг 1", 10)
  .then((v) => step("шаг 2", v))
  .then((v) => step("шаг 3", v))
  .then((v) => console.log("итог:", v));

Вывод:

шаг 1 -> 10
шаг 2 -> 11
шаг 3 -> 12
итог: 13

Сравните с callback hell из прошлого урока — здесь шаги читаются сверху вниз, а одна .catch в конце поймает ошибку с любого этапа.

Promise.all — несколько дел сразу

Если операции независимы, их запускают параллельно через Promise.all. Он ждёт, пока выполнятся ВСЕ, и отдаёт массив результатов:

const p1 = Promise.resolve("пользователь");
const p2 = Promise.resolve("настройки");
const p3 = Promise.resolve("уведомления");

Promise.all([p1, p2, p3]).then((results) => {
  console.log("Все загружены:", results);
});

Вывод:

Все загружены: [ 'пользователь', 'настройки', 'уведомления' ]

Это быстрее, чем грузить по очереди: все три «уехали» одновременно. Если хоть один промис упадёт, Promise.all сразу перейдёт в .catch. Когда же вам нужны результаты всех операций независимо от того, какие из них упали, берут Promise.allSettled — он дожидается всех и для каждого сообщает, успех это был или ошибка.

Итог

  • Промис — обещание будущего результата: pending → fulfilled / rejected.
  • Успех ловят через .then, ошибку — через .catch.
  • Цепочка .then заменяет вложенные колбэки плоской последовательностью.
  • Promise.all запускает независимые операции параллельно и ждёт все.
Проверьте себя
1. В каких трёх состояниях может быть промис?
Astart, run, stop
Bpending, fulfilled, rejected
Copen, closed, error
Dwait, done, fail
2. Как поймать ошибку промиса?
A.then
B.catch
C.error
Dtry
3. Что делает Promise.all?
AЗапускает промисы по очереди
BЖдёт выполнения всех переданных промисов и возвращает массив результатов
CОтменяет все промисы
DБерёт первый завершившийся
Поддержать проект