Promise (базово)

Урок: Promise

Введение

В предыдущем уроке мы говорили об асинхронности — о том, как программа может выполнять задачи без остановки.

Но возникает следующая проблема: как работать с результатом асинхронной операции?

Представь, что ты заказал доставку еды. Ты не знаешь точно, когда она приедет, но у тебя есть «обещание», что она будет доставлена — либо успешно, либо с ошибкой.

В программировании ситуация похожая. Когда мы отправляем запрос на сервер, мы не получаем результат сразу. Но нам нужен способ:

  • дождаться результата,
  • обработать его,
  • или обработать ошибку.

Для этого в JavaScript существует Promise.


Что такое Promise на практике

Promise — это объект, который представляет результат асинхронной операции.

Проще говоря, это «обещание», что операция завершится:

  • либо успешно,
  • либо с ошибкой.

У Promise есть три состояния:

  • ожидание (pending),
  • выполнено успешно (fulfilled),
  • выполнено с ошибкой (rejected).

Но важнее понять не термины, а идею: Promise — это контейнер для будущего результата.


Создание простого Promise и then

Рассмотрим пример, который полностью выполняется в одном фрагменте: создаём Promise и сразу подписываемся на результат.

let promise = new Promise(function (resolve, reject) {
  setTimeout(() => {
    resolve('Готово!');
  }, 2000);
});

promise.then(function (result) {
  console.log(result);
});

Разберём:

  • new Promise(...) — создаём новый Promise;
  • внутрь передаётся функция;
  • resolve — функция, которая сообщает об успешном завершении;
  • reject — функция, которая сообщает об ошибке;
  • then подписывается на успех: когда вызовется resolve, в колбэк придёт значение.

Через 2 секунды вызывается resolve('Готово!') — в консоли появится Готово!.


Обработка ошибок через catch

Если что-то пошло не так, используется reject.

let promise = new Promise(function (resolve, reject) {
  setTimeout(() => {
    reject('Ошибка!');
  }, 2000);
});

promise.catch(function (error) {
  console.log(error);
});

Результат:

Ошибка!

Метод catch срабатывает, если Promise завершился с ошибкой.


Цепочка then

Одна из сильных сторон Promise — возможность строить цепочки.

let promise = new Promise(function (resolve) {
  resolve(2);
});

promise
  .then(function (num) {
    return num * 2;
  })
  .then(function (num) {
    return num * 3;
  })
  .then(function (result) {
    console.log(result);
  });

Результат:

12

Разберём:

  • первый then получает 2 → возвращает 4;
  • второй получает 4 → возвращает 12;
  • третий получает 12 → выводит результат.

Каждый then получает результат предыдущего.


Более короткая запись (стрелочные функции)

Часто Promise пишут с использованием стрелочных функций:

let promise = new Promise((resolve) => {
  resolve(5);
});

promise.then((num) => num * 2).then((num) => console.log(num));

Это тот же код, но более компактный.


Пример с имитацией запроса

Представим, что мы «загружаем данные»:

function fetchData() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve('Данные получены');
    }, 2000);
  });
}

fetchData().then((data) => {
  console.log(data);
});

Результат через 2 секунды:

Данные получены

Здесь:

  • функция возвращает Promise;
  • then получает результат;
  • код не блокируется.

Почему Promise лучше callback

Ранее для асинхронности использовали callback-функции:

setTimeout(() => {
  console.log('Готово');
}, 2000);

Но при сложной логике получаются вложенные функции. Ниже — учебная имитация: простые шаги вызывают следующий колбэк (в реальности вместо cb() могли бы быть таймеры или запросы).

function step1(cb) {
  cb();
}

function step2(cb) {
  cb();
}

function step3(cb) {
  cb();
}

step1(() => {
  step2(() => {
    step3(() => {
      console.log('Готово');
    });
  });
});

Это называется «callback hell».

Promise решает эту проблему, делая код последовательным и читаемым через цепочки then.


Где это используется на практике

Promise используется везде, где есть асинхронность:

  • запросы к серверу (fetch, axios);
  • работа с файлами;
  • таймеры;
  • взаимодействие с API;
  • загрузка данных.

Практически любая современная библиотека или API работает через Promise.


Итоговое понимание

Promise — это способ работать с результатом асинхронной операции.

Он позволяет:

  • дождаться результата;
  • обработать успех или ошибку;
  • строить цепочки действий.

Ключевая идея в том, что Promise — это «обещание результата в будущем». Мы не получаем данные сразу, но можем заранее описать, что делать, когда они появятся.

Это делает асинхронный код более понятным, управляемым и последовательным.