Promise: состояние pending, fulfilled, rejected
Что такое Promise и зачем нужны состояния? 🤔
Promise (Обещание) — это объект, представляющий результат асинхронной операции. Он может находиться в одном из трёх состояний:
pending(ожидание) — начальное состояние, операция ещё не завершенаfulfilled(выполнено) — операция успешно завершенаrejected(отклонено) — операция завершена с ошибкой
Представьте, что Promise — это пицца, которую вы заказали. Пока её готовят — это pending. Когда привозят горячую и вкусную — fulfilled. А если курьер уронил коробку — увы, rejected.
Как работает состояние pending ⏳
Каждый Promise начинается со состояния pending. В этот момент асинхронная операция ещё выполняется, и мы не знаем, чем всё закончится.
const pizzaPromise = new Promise((resolve, reject) => {
// Здесь пицца ещё готовится
});
console.log(pizzaPromise); // Promise { <pending> }
💡 Проверить состояние можно через
.then(),.catch()илиfinally(), но сам объект Promise не предоставляет прямого доступа к текущему состоянию.
Переход в fulfilled — успешное выполнение 🎉
Когда асинхронная операция завершается успешно, Promise переходит в состояние fulfilled, вызывая функцию resolve:
const successPromise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Пицца доставлена!"); // Переход в fulfilled
}, 2000);
});
successPromise.then(result => {
console.log(result); // "Пицца доставлена!"
});
После перехода в fulfilled Promise запоминает своё значение навсегда (это называется "урегулирование" Promise).
Переход в rejected — когда что-то пошло не так 💥
Если в процессе выполнения возникает ошибка, Promise переходит в состояние rejected через функцию reject:
const failedPromise = new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error("Курьер попал в пробку!")); // Переход в rejected
}, 2000);
});
failedPromise.catch(error => {
console.error(error.message); // "Курьер попал в пробку!"
});
Как и с fulfilled, после перехода в rejected Promise больше не может изменить своё состояние.
Жизненный цикл Promise в картинках 🖼️
Вот как выглядит полный цикл жизни Promise:
+-------------------+
| pending |
+---------+---------+
|
+---------v---------+
| fulfilled (resolve) |
+-------------------+
|
+---------v---------+
| rejected (reject) |
+-------------------+
🎯 Важно: Promise может перейти ТОЛЬКО ИЗ
pendingв ЛИБОfulfilled, ЛИБОrejected. Обратного пути нет!
Практический пример: загрузка данных с сервера 🌐
Давайте рассмотрим реальный пример с fetch, который возвращает Promise:
const loadUserData = (userId) => {
return new Promise((resolve, reject) => {
fetch(`https://api.example.com/users/${userId}`)
.then(response => {
if (!response.ok) {
reject(new Error('Пользователь не найден'));
}
return response.json();
})
.then(data => resolve(data))
.catch(error => reject(error));
});
};
// Использование
loadUserData(123)
.then(user => console.log('Данные:', user))
.catch(err => console.error('Ошибка:', err));
Здесь мы видим все три состояния:
pending— пока идёт запросfulfilled— если сервер вернул данныеrejected— если возникла ошибка
Важные особенности состояний 🧠
1. Одноразовость: Promise может изменить состояние только один раз. Последующие вызовы resolve/reject игнорируются.
const promise = new Promise((resolve, reject) => {
resolve('Первый вызов');
reject('Второй вызов'); // Игнорируется!
resolve('Третий вызов'); // Тоже игнорируется!
});
2. Немедленное урегулирование: Можно создать уже разрешённый Promise:
const fulfilledPromise = Promise.resolve('Готово сразу!');
const rejectedPromise = Promise.reject(new Error('Сразу ошибка'));
3. Цепочки Promise: Каждый .then() возвращает новый Promise, что позволяет строить цепочки.
Как избежать "зависших" Promise? 🛑
Promise, который никогда не выходит из состояния pending, может вызвать утечки памяти. Всегда предусматривайте завершение:
// Плохо — Promise может зависнуть
const unsafePromise = new Promise(() => {
// Нет вызова resolve/reject
});
// Хорошо — таймаут на завершение
const safePromise = new Promise((resolve, reject) => {
const timer = setTimeout(() => {
reject(new Error('Таймаут выполнения'));
}, 5000);
// Какая-то асинхронная операция
someAsyncOperation()
.then(resolve)
.catch(reject)
.finally(() => clearTimeout(timer));
});
Подведём итоги 🏁
- Promise — это "контейнер" для асинхронной операции с тремя состояниями
- Начинается всегда с
pending, затем переходит вfulfilled— при успешном выполнении (вызовresolve) иrejected— при ошибке (вызовreject) - Состояние меняется только один раз и навсегда
- Используйте
.then(),.catch()иfinally()для реакции на изменения состояния
Теперь вы понимаете "анатомию" Promise настолько хорошо, что сможете объяснить её даже своему коту! Ну, или коллеге — кому как повезёт больше. 🐱💻