Промисы: Promise, then, catch

Promise в JavaScript: создание промиса, цепочки then/catch/finally — чистая альтернатива вложенным колбэкам.

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

Создание промиса

Промис создаётся через new Promise(executor). executor — это функция с двумя параметрами: resolve (вызывают при успехе) и reject (при ошибке).

const p = new Promise((resolve, reject) => {
  const success = true;

  if (success) {
    resolve('Всё хорошо!');
  } else {
    reject(new Error('Что-то пошло не так'));
  }
});

console.log(p); // Promise { 'Всё хорошо!' }

Вывод:

Promise { 'Всё хорошо!' }

then, catch, finally

.then(onFulfilled) выполняется, когда промис выполнен. .catch(onRejected) — при ошибке. .finally(fn) — в любом случае. Они возвращают новый промис, поэтому их можно выстраивать в цепочку.

function fetchScore(userId) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (userId > 0) {
        resolve({ userId, score: 95 });
      } else {
        reject(new Error('Неверный ID'));
      }
    }, 300);
  });
}

fetchScore(1)
  .then(data => {
    console.log('Результат:', data.score);
    return data.score * 2; // передаём дальше по цепочке
  })
  .then(doubled => console.log('Удвоено:', doubled))
  .catch(err => console.log('Ошибка:', err.message))
  .finally(() => console.log('Готово'));

Вывод:

Результат: 95
Удвоено: 190
Готово

Ошибочный промис

fetchScore(-1)
  .then(data => console.log('Данные:', data))
  .catch(err => console.log('Ошибка:', err.message))
  .finally(() => console.log('Завершено'));

Вывод:

Ошибка: Неверный ID
Завершено

Promise.all — параллельное ожидание

Promise.all([p1, p2, ...]) ждёт, пока все промисы выполнятся, и возвращает массив результатов. Если хоть один отклоняется — весь Promise.all отклоняется.

const p1 = Promise.resolve(10);
const p2 = Promise.resolve(20);
const p3 = Promise.resolve(30);

Promise.all([p1, p2, p3])
  .then(values => {
    console.log(values);         // [10, 20, 30]
    console.log(values.reduce((a, b) => a + b, 0)); // 60
  });

Вывод:

[10, 20, 30]
60

Всегда добавляйте .catch к промисам. Необработанный rejected-промис вызывает предупреждение (или ошибку в Node.js) и может приводить к молчаливым сбоям.

Коротко

  • Промис — объект с тремя состояниями: pending, fulfilled, rejected.
  • .then обрабатывает успех, .catch — ошибку, .finally — оба случая.
  • Методы возвращают новый промис — можно строить цепочки.
  • Promise.all ждёт все промисы параллельно и возвращает массив результатов.
Проверьте себя
1. Сколько состояний у промиса?
A1
B2
C3
D4
2. Что обрабатывает метод .catch()?
AУспешное выполнение промиса
BОтклонённый (rejected) промис или исключение в .then
CОба случая
DТолько синхронные ошибки
3. Promise.all([p1, p2, p3]) — что произойдёт, если p2 завершится с ошибкой?
AВернёт результаты p1 и p3
BВесь Promise.all отклонится
Cp2 будет проигнорирован
DВыполнение остановится
Поддержать проект