Что такое Promise
Promise (обещание) — это встроенный объект в JavaScript, предназначенный для работы с асинхронными операциями. Он представляет значение, которое может быть доступно сейчас, в будущем или никогда, и позволяет писать асинхронный код в более структурированной и читаемой форме, чем традиционные коллбэки.
🔹 Основная идея
Асинхронный код часто сопровождается отложенными результатами (например, запрос на сервер или чтение файла). Promise — это обёртка над этими результатами, которая даёт удобный способ:
-
ждать результата,
-
обработать успех или ошибку,
-
цеплять действия (chain),
-
управлять несколькими параллельными операциями.
🔹 Состояния Promise
Каждый Promise имеет одно из трёх состояний:
-
Pending (ожидание) — начальное состояние, операция ещё не завершена.
-
Fulfilled (выполнено) — операция завершена успешно, и результат доступен.
-
Rejected (отклонено) — операция завершилась с ошибкой.
После перехода из pending в fulfilled или rejected, состояние становится неизменяемым.
🔹 Создание Promise
const promise = new Promise((resolve, reject) => {
// Асинхронная операция
if (успех) {
resolve('результат');
} else {
reject('ошибка');
}
});
Функция-исполнитель принимает два аргумента:
- resolve(value) — вызов при успешном завершении;
- reject(error) — вызов при ошибке.
🔹 Использование .then(), .catch(), .finally()
.then(onFulfilled, onRejected)
Обрабатывает успешное завершение:
promise
.then((result) => {
console.log('Успех:', result);
})
.catch((error) => {
console.log('Ошибка:', error);
});
-
.then() возвращает новый Promise, позволяя создавать цепочки (chaining).
-
.catch() — сокращённая форма .then(null, onRejected).
-
.finally() — вызывается независимо от результата.
promise
.finally(() => console.log('Завершено'))
.then((result) => console.log(result))
.catch((err) => console.log(err));
🔹 Цепочка промисов
fetchData()
.then((data) => processData(data))
.then((result) => sendToServer(result))
.then(() => console.log('Готово!'))
.catch((err) => console.error('Ошибка:', err));
Каждое звено в цепи .then() обрабатывает результат предыдущего.
🔹 Асинхронная ошибка
Если в .then() или другом обработчике возникает ошибка, она автоматически переходит в catch():
promise
.then(() => {
throw new Error("Ошибка!");
})
.catch((e) => console.log(e.message)); // Выведет: "Ошибка!"
🔹 Статические методы Promise
Promise.resolve(value)
Создаёт успешно завершённый промис с заданным значением.
Promise.resolve(5).then((x) => console.log(x)); // 5
Promise.reject(error)
Создаёт промис, завершённый с ошибкой.
Promise.reject('ошибка').catch((e) => console.log(e)); // ошибка
Promise.all(iterable)
Ожидает выполнения всех промисов. Возвращает промис с массивом результатов. Если хотя бы один промис отклонён — Promise.all завершится с ошибкой.
Promise.all(\[p1, p2, p3\])
.then((\[r1, r2, r3\]) => console.log(r1, r2, r3))
.catch((err) => console.log('Ошибка:', err));
Promise.allSettled(iterable)
Ожидает выполнения всех промисов, но не отклоняется даже при ошибках. Возвращает массив объектов с результатами:
Promise.allSettled(\[
Promise.resolve('OK'),
Promise.reject('Fail')
\]).then(console.log);
Promise.race(iterable)
Возвращает результат первого завершившегося промиса — независимо от успеха или ошибки.
Promise.race(\[p1, p2\])
.then((result) => console.log('Победил:', result));
Promise.any(iterable)
Ожидает первый успешный промис. Если все завершились с ошибкой, то промис отклоняется с AggregateError.
Promise.any(\[
Promise.reject('e1'),
Promise.resolve('успех')
\]).then(console.log);
🔹 Пример: имитация асинхронного запроса
function fakeApiCall(success = true) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (success) {
resolve('Данные получены');
} else {
reject('Ошибка при получении данных');
}
}, 1000);
});
}
fakeApiCall()
.then(console.log)
.catch(console.error);
🔹 Использование с async/await
Хотя async/await является синтаксическим сахаром над Promise, они тесно связаны:
async function getData() {
try {
const result = await fakeApiCall();
console.log(result);
} catch (e) {
console.error(e);
}
}
await приостанавливает выполнение функции до завершения промиса и возвращает его результат или бросает ошибку, если промис отклонён.
🔹 Внутреннее устройство промиса
В JavaScript движках (например, V8), Promise реализован через:
-
очереди микрозадач (Microtasks Queue);
-
замыкания для хранения состояния;
-
коллбеки, сохраняемые до момента завершения промиса.
Каждый then() не исполняется мгновенно, а добавляется в очередь после текущего выполнения скрипта, что гарантирует предсказуемый порядок исполнения.
🔹 Проблемы и ограничения
-
Promise не может быть отменён (нужно использовать AbortController).
-
Не обрабатывает асинхронные итерации (решается через async generators).
-
Ошибки могут "теряться", если .catch() не добавлен.
-
Может усложнить отладку при глубокой вложенности или небрежной архитектуре.
Таким образом, Promise — мощный инструмент асинхронного программирования в JavaScript, который делает возможным управление отложенными операциями, их комбинацией, обработкой ошибок и построением предсказуемых, безопасных цепочек событий.