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 orderPromise.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 sequentialPromise.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 — локальная установка не требуется.
Все уроки этого курса
- Цикл событий: стек вызовов, очередь и микрозадачи
- Колбэки и ад колбэков
- Promise: then, catch, finally и Promise.all
- async/await и обработка ошибок