0Pricing
Frontend Academy · Урок

Promise: then, catch, finally и Promise.all

Создавайте цепочки Promise, обрабатывайте ошибки в блоках catch, выполняйте очистку в finally и запускайте несколько Promise параллельно с помощью Promise.all.

«Promise: then, catch, finally и Promise.all» — бесплатный урок Frontend Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Frontend Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Frontend Academy содержит 4 уроков всего.

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

Промис представляет значение, которое станет доступно в будущем. Это объект в одном из трёх состояний: ожидание (начальное состояние), выполнен (завершён с некоторым значением) или отклонён (завершён с причиной ошибки). После завершения состояние промиса становится постоянным.

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

Создайте промис с помощью конструктора new Promise(executor). Функция-исполнитель получает функции обратного вызова resolve и reject. Вызовите resolve со значением успешного результата или reject с ошибкой.

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

const fetchData = (url) => new Promise((resolve, reject) => {
  fetch(url)
    .then(res => res.json())
    .then(resolve)
    .catch(reject);
});

.then() — обработка успешного результата

promise.then(onFulfilled) регистрирует функцию обратного вызова, которая выполняется после выполнения промиса. Она получает разрешённое значение. .then() возвращает новый промис, что позволяет создавать цепочки.

fetch('/api/users')
  .then(response => response.json())
  .then(users => {
    console.log('Users:', users);
    return users.length;
  })
  .then(count => console.log('Count:', count));

.catch() — обработка ошибок

promise.catch(onRejected) обрабатывает отклонения. Если поместить его в конец цепочки, он перехватит любую ошибку на любом предыдущем шаге.

fetch('/api/data')
  .then(res => {
    if (!res.ok) throw new Error(`HTTP ${res.status}`);
    return res.json();
  })
  .then(data => processData(data))
  .catch(err => {
    console.error('Failed:', err.message);
    showErrorToUser();
  });

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

promise.finally(onFinally) выполняется независимо от того, был ли промис выполнен или отклонён. Это идеально подходит для очистки: скрытия индикатора загрузки, освобождения блокировки и записи аналитики.

showSpinner();
fetch('/api/data')
  .then(res => res.json())
  .then(render)
  .catch(handleError)
  .finally(() => hideSpinner()); // always runs

Цепочки промисов — возврат значений

Верните значение из .then(), и оно станет разрешённым значением для следующего .then(). Верните новый промис, чтобы последовательно связать асинхронные операции.

getUser(id)
  .then(user => getOrders(user.id))  // return Promise
  .then(orders => orders[0])          // return value
  .then(order => console.log(order)); // receive order

Promise.all() — параллельное выполнение

Promise.all([p1, p2, p3]) ждёт выполнения всех промисов и возвращает массив результатов в том же порядке. Если какой-либо промис отклоняется, вся операция немедленно отклоняется.

const [user, posts, comments] = await Promise.all([
  fetch('/api/user/1').then(r => r.json()),
  fetch('/api/posts').then(r => r.json()),
  fetch('/api/comments').then(r => r.json()),
]);
// All three run in parallel — much faster than sequential

Promise.allSettled() — без немедленного отказа

Promise.allSettled() ждёт завершения всех промисов (выполнения или отклонения) и возвращает массив объектов результатов с полями {status, value} или {status, reason}. Это полезно, когда нельзя допустить, чтобы одна ошибка привела к потере всех результатов.

const results = await Promise.allSettled([p1, p2, p3]);
results.forEach(result => {
  if (result.status === 'fulfilled') use(result.value);
  else logError(result.reason);
});

Promise.race() и Promise.any()

Promise.race() завершается с результатом или ошибкой первого завершившегося промиса. Promise.any() завершается с результатом первого выполненного промиса (игнорирует отклонения и отклоняется, только если отклонены все промисы). Это полезно для ограничений времени ожидания и резервирования.

// Timeout pattern:
const withTimeout = (promise, ms) => Promise.race([
  promise,
  new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout')), ms))
]);

Создание уже завершённых промисов

Promise.resolve(value) создаёт промис, уже выполненный со значением value. Promise.reject(error) создаёт уже отклонённый промис. Это полезно для тестирования и функций-адаптеров.

const p = Promise.resolve(42);
p.then(v => console.log(v)); // 42

События необработанных отклонений

Если промис отклоняется без обработчика ошибок, возникает необработанное отклонение. Современные браузеры и Node.js выводят предупреждения. Всегда добавляйте обработчик отклонений или используйте конструкцию обработки ошибок с асинхронными функциями и ожиданием.

window.addEventListener('unhandledrejection', event => {
  console.error('Unhandled rejection:', event.reason);
  event.preventDefault();
});

Быстрая проверка

Какой статический метод запускает несколько промисов параллельно и завершается с массивом всех результатов?

Итоги: промисы

Используйте обработчик then для успешного результата, обработчик ошибок для ошибок и обработчик очистки для завершающих действий. Цепочки передают значения дальше. Promise.all() выполняет операции параллельно. Promise.allSettled() допускает частичные ошибки. Promise.race() выбирает самый быстрый результат. Всегда обрабатывайте отклонения. В современном коде асинхронные функции с ожиданием служат синтаксическим сахаром над промисами.

Часто задаваемые вопросы

Урок «Promise: then, catch, finally и Promise.all» бесплатный?

Да — полный текст урока «Promise: then, catch, finally и Promise.all» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Frontend Academy, подпишись на CoddyKit PRO. Курс Frontend Academy содержит 4 уроков всего.

Чему я научусь в уроке «Promise: then, catch, finally и Promise.all»?

Создавайте цепочки Promise, обрабатывайте ошибки в блоках catch, выполняйте очистку в finally и запускайте несколько Promise параллельно с помощью Promise.all. Ты практикуешь Frontend Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Frontend Academy?

Предыдущий опыт не требуется. Frontend Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.

Сколько времени занимает урок «Promise: then, catch, finally и Promise.all»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Frontend Academy?

Да. Каждый урок Frontend Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Цикл событий: стек вызовов, очередь и микрозадачи
  2. Колбэки и ад колбэков
  3. Promise: then, catch, finally и Promise.all
  4. async/await и обработка ошибок
← Назад к Frontend Academy