JS Tower
JavaScript & TypeScriptМодуль 5: Асинхронность

Промисы

Работа с асинхронными операциями

Цель урока

В этом уроке ты научишься:

  • Создавать промисы
  • Обрабатывать результаты и ошибки
  • Строить цепочки промисов

Что такое Promise

Promise (промис) — объект, представляющий результат асинхронной операции.

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

  • pending — ожидание
  • fulfilled — выполнено успешно
  • rejected — выполнено с ошибкой
let promise = new Promise((resolve, reject) => {
  // Асинхронная операция
  setTimeout(() => {
    let success = true;
    
    if (success) {
      resolve("Данные получены");
    } else {
      reject("Ошибка загрузки");
    }
  }, 1000);
});

then, catch, finally

then — обработка успеха

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

catch — обработка ошибки

promise.catch(error => {
  console.log(error); // "Ошибка загрузки"
});

finally — выполняется всегда

promise.finally(() => {
  console.log("Операция завершена");
});

Полный пример

promise
  .then(result => console.log("Успех:", result))
  .catch(error => console.log("Ошибка:", error))
  .finally(() => console.log("Завершено"));

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

fetch("/api/user")
  .then(response => response.json())
  .then(user => fetch("/api/posts/" + user.id))
  .then(response => response.json())
  .then(posts => console.log(posts))
  .catch(error => console.log("Ошибка:", error));

Возврат значений

Promise.resolve(1)
  .then(x => x + 1)    // 2
  .then(x => x * 2)    // 4
  .then(x => x + 3)    // 7
  .then(x => console.log(x)); // 7

Возврат промиса

Promise.resolve(1)
  .then(x => {
    return new Promise(resolve => {
      setTimeout(() => resolve(x + 1), 1000);
    });
  })
  .then(x => console.log(x)); // 2 (через 1 секунду)

Обработка ошибок

Ошибка в цепочке

Promise.resolve(1)
  .then(x => {
    throw new Error("Ошибка!");
  })
  .then(x => console.log("Не выполнится"))
  .catch(error => console.log("Поймано:", error.message))
  .then(() => console.log("Продолжаем"));

// Поймано: Ошибка!
// Продолжаем

Пробрасывание ошибки

promise
  .catch(error => {
    console.log("Логируем:", error);
    throw error; // пробрасываем дальше
  })
  .catch(error => {
    console.log("Обрабатываем:", error);
  });

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

Promise.resolve

let resolved = Promise.resolve("Готово");
resolved.then(x => console.log(x)); // "Готово"

Promise.reject

let rejected = Promise.reject("Ошибка");
rejected.catch(x => console.log(x)); // "Ошибка"

Промисификация

function delay(ms) {
  return new Promise(resolve => {
    setTimeout(resolve, ms);
  });
}

delay(1000).then(() => console.log("Прошла секунда"));

Практические примеры

Загрузка данных

function fetchUser(id) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (id > 0) {
        resolve({ id, name: "Иван" });
      } else {
        reject("Неверный ID");
      }
    }, 1000);
  });
}

fetchUser(1)
  .then(user => console.log(user))
  .catch(error => console.log(error));

Повторные попытки

function fetchWithRetry(url, retries = 3) {
  return fetch(url).catch(error => {
    if (retries > 0) {
      console.log(`Попытка ${4 - retries}`);
      return fetchWithRetry(url, retries - 1);
    }
    throw error;
  });
}

Практика

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

Задача: Создай промис, который разрешается через 1 секунду.

Loading...
Ваш вывод:

Задание 2: Цепочка

Задача: Создай цепочку, удваивающую число 3 раза.

Запустите код для проверки
Loading...
Ваш вывод:
Ожидаемый результат:
16

Задание 3: Обработка ошибок

Задача: Обработай ошибку и продолжи выполнение.

Запустите код для проверки
Loading...
Ваш вывод:
Ожидаемый результат:
Ошибка обработана
Продолжаем

Проверь себя

  1. Какие состояния у Promise?
  2. Чем then отличается от catch?
  3. Что делает finally?