JS Async

Промисы (Promises)

Понять, что Promise — это объект, представляющий будущий результат операции, и научиться создавать и использовать промисы с then/catch/finally.

Средний (Intermediate)

Кратко

Promise — объект, представляющий результат операции, который станет известен позже. У него три состояния: pending (ожидание), fulfilled (выполнено), rejected (ошибка). then обрабатывает успех, catch — ошибку, finally — завершение в любом случае.


Подробно

Создание Promise: const promise = new Promise((resolve, reject) => { // Асинхронная операция setTimeout(() => { resolve('Успех!'); // fulfilled // или reject('Ошибка!'); // rejected }, 1000); });

Три состояния:

  • Pending — операция выполняется
  • Fulfilled — resolve вызван → результат доступен
  • Rejected — reject вызван → ошибка доступна

После fulfilled/rejected состояние НЕ меняется.

Использование: promise .then(result => console.log(result)) // 'Успех!' .catch(error => console.log(error)) .finally(() => console.log('Завершено'));

Цепочка then: fetchUser(1) .then(user => fetchPosts(user.id)) .then(posts => console.log(posts)) .catch(error => console.log(error));

Каждый .then возвращает НОВЫЙ Promise.

Promise.all: const p1 = fetch('/api/users'); const p2 = fetch('/api/posts'); Promise.all([p1, p2]) .then(([users, posts]) => { /* оба готовы */ }) .catch(error => { /* хотя бы один отклонён */ });


Ментальная модель

Promise — как квитанция в ресторане. Вы сделали заказ (вызвали Promise). Вам дали квитанцию (Promise object). Когда еда готова (resolve) — вам принесут блюдо (result). Если кухня закрылась (reject) — вам сообщат об ошибке. Вы можете пойти гулять (другий код выполняется) пока ждёте.


Примеры

**Самый простой:**

javascript
const promise = new Promise((resolve) => {
  setTimeout(() => resolve('Готово!'), 1000);
});

promise.then(result => console.log(result));
// Через 1 сек: 'Готово!'

Простейший Promise: resolve через 1 секунду.

**Простой:**

javascript
function divide(a, b) {
  return new Promise((resolve, reject) => {
    if (b === 0) {
      reject(new Error('Деление на ноль!'));
    } else {
      resolve(a / b);
    }
  });
}

divide(10, 2)
  .then(result => console.log(result))  // 5
  .catch(error => console.log(error.message));

divide(10, 0)
  .then(result => console.log(result))
  .catch(error => console.log(error.message)); // 'Деление на ноль!'

Promise с валидацией: resolve для успеха, reject для ошибки.

**Реальный пример:**

javascript
function fetchUserData(userId) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (userId > 0) {
        resolve({ id: userId, name: 'Анна', email: 'anna@test.com' });
      } else {
        reject(new Error('Неверный ID'));
      }
    }, 500);
  });
}

// Цепочка промисов:
fetchUserData(1)
  .then(user => {
    console.log(`Загружен: ${user.name}`);
    return fetchUserData(2);
  })
  .then(user => {
    console.log(`Загружен: ${user.name}`);
  })
  .catch(error => {
    console.log(`Ошибка: ${error.message}`);
  })
  .finally(() => {
    console.log('Загрузка завершена');
  });

Цепочка then: каждый шаг возвращает новый Promise.


Частые ошибки

**Неправильно:** Забывать catch в цепочке then

**Почему:** Без catch ошибка промиса «зависает» — не обрабатывается.

**Правильно:** Всегда завершайте цепочку .catch() или используйте try/catch с async/await.

**Неправильно:** Думать, что Promise автоматически делает код async

**Почему:** Promise — это ОБЪЕКТ, представляющий результат. Код внутри new Promise выполняется синхронно до первого асинхронного действия.

**Правильно:** Promise — обёртка для результата, который приходит позже.

**Неправильно:** Вызывать resolve/reject несколько раз

**Почему:** Только первый вызов имеет эффект. Остальные игнорируются.

**Правильно:** resolve/reject — одноразовые. Один промис — одно решение.


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

  • Promise: pending → fulfilled или rejected
  • resolve(result) — успешное завершение
  • reject(error) — ошибка
  • .then() — обработка успеха
  • .catch() — обработка ошибки
  • .finally() — завершение в любом случае
  • Каждый .then возвращает новый Promise

Связь

Назад: Вы понимаете callback-функции и таймеры (JA1-JA3) — промисы это структурированный способ обработки асинхронных результатов.

Вперёд: Следующий урок (JA5) — async/await: синтаксический сахар над промисами.


Читайте дальше

Материалы курса JS Async — PROlab Academy.