← Назад к вопросам

Что такое промисы?

1.0 Junior🔥 252 комментариев
#JavaScript Core

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое промисы в JavaScript?

Промис (Promise) — это специальный объект в JavaScript, который представляет собой асинхронную операцию, находящуюся в одном из трёх возможных состояний: pending (ожидание), fulfilled (выполнено успешно) или rejected (выполнено с ошибкой). Промисы были введены в стандарте ES6 (2015 год) как решение проблемы "ада обратных вызовов" (callback hell), предоставляя более удобный и структурированный способ работы с асинхронным кодом.

Ключевые характеристики промисов

  • Состояния (States):
    *   **`pending`** — начальное состояние, операция ещё не завершена.
    *   **`fulfilled`** — операция завершилась успешно.
    *   **`rejected`** — операция завершилась с ошибкой.
    Переход из `pending` в `fulfilled` или `rejected` является **финальным** — состояние промиса больше не меняется.

  • Результат (Settlement):
    *   При переходе в `fulfilled` промис имеет **значение (value)**.
    *   При переходе в `rejected` промис имеет **причину (reason)** — обычно объект ошибки.

Базовый синтаксис и методы

Промис создаётся с помощью конструктора new Promise(), который принимает исполнительную функцию (executor). Эта функция, в свою очередь, принимает два callback-параметра: resolve и reject.

const myPromise = new Promise((resolve, reject) => {
  // Асинхронная или долгая операция
  setTimeout(() => {
    const success = Math.random() > 0.5;
    if (success) {
      resolve('Данные успешно получены!'); // Переводим промис в fulfilled
    } else {
      reject(new Error('Что-то пошло не так!')); // Переводим промис в rejected
    }
  }, 1000);
});

Для потребления результата промиса используются методы then(), catch() и finally().

myPromise
  .then((value) => {
    // Выполнится, если промис перешёл в fulfilled
    console.log('Успех:', value);
  })
  .catch((error) => {
    // Выполнится, если промис перешёл в rejected
    console.error('Ошибка:', error.message);
  })
  .finally(() => {
    // Выполнится в любом случае (после then/catch) — для очистки ресурсов
    console.log('Операция завершена (успех или ошибка)');
  });

Статические методы и композиция

Одно из главных преимуществ промисов — возможность удобной композиции асинхронных операций.

  • Promise.all() — ожидает выполнения ВСЕХ промисов в массиве. Возвращает массив результатов. Если хотя бы один отклоняется — вся операция отклоняется.

    Promise.all([fetch('/api/user'), fetch('/api/posts')])
      .then(([user, posts]) => console.log(user, posts));
    
  • Promise.allSettled() (ES2020) — ждёт завершения ВСЕХ промисов (успех или ошибка). Возвращает массив объектов с статусом и значением/ошибкой.

    Promise.allSettled([promise1, promise2])
      .then((results) => results.forEach((result) => console.log(result.status)));
    
  • Promise.race() — возвращает результат первого УСПЕШНО выполнившегося или отклонённого промиса.

    Promise.race([fetch('/api'), timeout(5000)])
      .then(handleData)
      .catch(handleTimeoutOrError);
    
  • Promise.any() (ES2021) — возвращает результат первого УСПЕШНО выполнившегося промиса. Отклоняется, если отклонятся ВСЕ промисы.

    Promise.any([backupApi1, backupApi2, backupApi3])
      .then((firstSuccess) => useData(firstSuccess));
    
  • Promise.resolve() / Promise.reject() — создают уже завершённые промисы (успешно или с ошибкой). Полезны для начала цепочки или приведения значения к промису.

Преимущества перед Callbacks

  • Читаемость и плоская структура: Цепочки .then() заменяют глубокую вложенность колбэков.
  • Централизованная обработка ошибок: Один метод .catch() в конце цепочки может перехватить любую ошибку, возникшую в любом из предыдущих звеньев.
  • Легкость композиции: Статические методы (all, race и др.) позволяют легко управлять несколькими асинхронными потоками.
  • Предсказуемость: Промис может быть разрешён или отклонён только один раз, что делает поток данных более контролируемым.

Эволюция: async/await

Промисы стали фундаментом для более позднего синтаксиса async/await (ES2017), который позволяет писать асинхронный код в почти синхронном стиле, сохраняя все преимущества промисов.

async function fetchData() {
  try {
    const response = await fetch('/api/data'); // "Ждём" разрешения промиса
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error('Ошибка загрузки:', error);
  }
}

Вывод: Промисы — это фундаментальный паттерн и встроенный класс в JavaScript для работы с асинхронностью. Они предоставляют мощный, композируемый и надёжный механизм для обработки операций, результат которых становится известен в будущем, и служат основой для современного асинхронного кода в языке.