Промисы (Promise)

Промис (Promise) — это встроенный в JavaScript объект, который представляет результат асинхронной операции, которая может завершиться успешно или с ошибкой. Промисы были созданы для решения проблем коллбэков и обеспечения более читаемого и управляемого асинхронного кода.

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

Любой промис может находиться в одном из трёх состояний:

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

Состояние промиса меняется только один раз: из pending либо в fulfilled, либо в rejected. После этого оно остаётся неизменным.

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

Промис создаётся с помощью конструктора new Promise(), которому передаётся функция-исполнитель (executor):

const myPromise = new Promise((resolve, reject) => {
  // Имитация асинхронной операции
  setTimeout(() => {
    const success = true;
    if (success) {
      resolve('Данные получены');
    } else {
      reject(new Error('Не удалось получить данные'));
    }
  }, 1000);
});

Функция получает два параметра:

  • resolve(value) — вызывается при успешном завершении
  • reject(error) — вызывается при ошибке

Обработка результата

Для работы с результатом промиса используются методы:

.then()

Вызывается, если промис выполнен успешно:

myPromise.then((result) => {
  console.log(result); // 'Данные получены'
});

.catch()

Вызывается, если промис отклонён:

myPromise.catch((error) => {
  console.error(error.message); // 'Не удалось получить данные'
});

.finally()

Вызывается в любом случае — как при успехе, так и при ошибке. Часто используется для очистки (например, скрыть индикатор загрузки):

myPromise
  .then(console.log)
  .catch(console.error)
  .finally(() => console.log('Операция завершена'));

Цепочка промисов

Метод .then() возвращает новый промис, что позволяет строить цепочки:

fetchUserData()
  .then(user => fetchUserPosts(user.id))
  .then(posts => processPosts(posts))
  .then(result => console.log(result))
  .catch(error => console.error('Ошибка:', error));

Каждый шаг может возвращать значение или другой промис. Если в цепочке возникает ошибка, выполнение переходит к ближайшему .catch().

Преимущества перед коллбэками

  • Код становится линейным и читаемым
  • Ошибки обрабатываются централизованно через .catch()
  • Легко комбинировать несколько асинхронных операций
  • Избегается «ад коллбэков»

Важно помнить

  • Промисы не отменяются после создания
  • Нельзя узнать текущее состояние промиса напрямую (только через обработчики)
  • Если не вызвать .catch(), ошибка может остаться незамеченной (в современных средах такие ошибки логируются в консоль)

Промисы стали стандартом для асинхронных операций в JavaScript и лежат в основе более современного синтаксиса async/await.