← Назад к вопросам
Какие свойства принимают then, catch и finally?
1.0 Junior🔥 151 комментариев
#JavaScript Core
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Свойства then, catch, finally в Promise
Основы Promise
Promise - объект для асинхронных операций. Он может находиться в трёх состояниях:
- Pending - операция не завершена
- Fulfilled - операция успешно завершена (резолв)
- Rejected - операция завершена с ошибкой (отклонена)
then()
then() принимает две колбэк-функции и возвращает новый Promise:
promise.then(
onFulfilled, // функция, вызывается при успехе
onRejected // функция, вызывается при ошибке (опционально)
)
Параметры onFulfilled:
- Получает значение (результат) от resolve()
- Должна вернуть значение или новый Promise
const promise = Promise.resolve(42);
promise.then((value) => {
console.log(value); // 42
return value * 2;
}).then((result) => {
console.log(result); // 84
});
Параметры onRejected:
- Получает причину ошибки (Rejection reason)
- Может вернуть значение (переводит в fulfilled) или выбросить ошибку
const promise = Promise.reject(new Error('Ошибка'));
promise.then(
undefined, // onFulfilled не нужен
(error) => {
console.log(error.message); // 'Ошибка'
return 'Восстановилось'; // Переводит в fulfilled
}
).then((value) => {
console.log(value); // 'Восстановилось'
});
Чейнирование then():
fetch('/api/user')
.then((response) => response.json())
.then((user) => {
console.log(user);
return fetch(`/api/posts/${user.id}`);
})
.then((response) => response.json())
.then((posts) => {
console.log(posts);
})
.catch((error) => console.error(error));
Важно: если onFulfilled или onRejected вернёт Promise, то цепь ждёт его разрешения.
catch()
catch() - это сокращение для .then(undefined, onRejected):
promise.catch(onRejected);
// Эквивалентно:
promise.then(undefined, onRejected);
Параметры catch():
- Получает причину ошибки
- Может обработать ошибку и вернуть значение (цепь продолжится с fulfilled)
- Может выбросить новую ошибку
const promise = Promise.reject(new Error('Сетевая ошибка'));
promise
.then((data) => data.json())
.catch((error) => {
console.error('Перехвачена ошибка:', error.message);
// Возвращаем значение - цепь продолжится с fulfilled
return { fallback: true };
})
.then((result) => {
console.log(result); // { fallback: true }
});
Полезный паттерн - обработка ошибок на разных этапах:
fetch('/api/user')
.then((response) => {
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return response.json();
})
.catch((error) => {
console.error('Ошибка загрузки пользователя:', error);
return null; // Продолжаем цепь с null
})
.then((user) => {
if (user) {
console.log(user);
} else {
console.log('Пользователь не загружен');
}
});
finally()
finally() - вызывается ВСЕГДА, независимо от результата (успех или ошибка):
promise.finally(onFinally)
Параметры finally():
- Не получает никаких параметров
- Может вернуть значение (обычно не возвращает)
- Если выбросит ошибку - цепь будет отклонена
- Не может менять результат Promise (в отличие от then/catch)
let isLoading = true;
fetch('/api/data')
.then((response) => response.json())
.then((data) => {
console.log(data);
})
.catch((error) => {
console.error(error);
})
.finally(() => {
isLoading = false; // Выполнится в любом случае
console.log('Загрузка завершена');
});
finally() не меняет результат:
Promise.resolve(42)
.finally(() => 'new value') // Это значение игнорируется
.then((value) => {
console.log(value); // 42, не 'new value'
});
Promise.reject(new Error('error'))
.finally(() => 'recovery') // Не восстанавливает
.catch((error) => {
console.log(error.message); // 'error'
});
Практический пример с finally():
function fetchWithSpinner(url) {
showSpinner();
return fetch(url)
.then((response) => response.json())
.then((data) => {
console.log('Данные получены:', data);
return data;
})
.catch((error) => {
console.error('Ошибка:', error);
showError('Не удалось загрузить данные');
throw error;
})
.finally(() => {
hideSpinner(); // Спиннер скроется в любом случае
});
}
Сравнение then/catch/finally
| Метод | Получает параметр | Меняет результат | Когда вызывается |
|---|---|---|---|
| then() | Да (value или error) | Да | При успехе или ошибке (в зависимости от версии) |
| catch() | Да (error) | Да | Только при ошибке |
| finally() | Нет | Нет | В любом случае |
Сложный пример - комбинация
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.5) {
resolve({ id: 1, name: 'Alice' });
} else {
reject(new Error('Случайная ошибка'));
}
}, 1000);
});
promise
.then((user) => {
console.log('Пользователь получен:', user);
return user.id;
})
.then((userId) => {
console.log('ID пользователя:', userId);
return fetch(`/api/posts/${userId}`);
})
.then((response) => response.json())
.catch((error) => {
console.error('Ошибка в цепи:', error.message);
return []; // Возвращаем пустой массив при ошибке
})
.finally(() => {
console.log('Загрузка завершена');
})
.then((posts) => {
console.log('Посты:', posts);
});
Ключевые выводы
- then() - основной метод для работы с результатом или ошибкой
- catch() - удобный способ обработки только ошибок
- finally() - для очистки ресурсов (закрытие спиннера, логирование и т.д.)
- Все три метода возвращают новый Promise, позволяя создавать цепи
- Ошибки распространяются вниз по цепи до первого catch()