Надежное приложение должно корректно обрабатывать ошибки. В асинхронном JavaScript это сложнее, чем в синхронном, из-за разрыва стека вызовов. Неправильная обработка может привести к «тихим» сбоям, которые трудно отладить.
Обработка в Promise и async/await
С появлением async/await код стал выглядеть синхронным, но ошибки все равно нужно ловить через try/catch. Важно помнить, что await превращает отклоненный Promise в исключение.
async function fetchData() {
try {
const response = await fetch('/api/data');
if (!response.ok) throw new Error('Network error');
const data = await response.json();
return data;
} catch (error) {
console.error('Ошибка загрузки:', error);
// Логирование или показ UI ошибки
return null;
}
}
Если вы забудете try/catch вокруг await, ошибка уйдет в глобальный обработчик unhandledrejection, и выполнение функции прервется.
Цепочки Promise и catch
В классических цепочках .then() ошибка ловится ближайшим .catch(). Важно понимать, что .catch() внутри цепочки может перехватить ошибку и вернуть новое значение, продолжив цепочку.
fetch('/api/user')
.then(res => res.json())
.catch(err => {
console.log('Поймали ошибку, возвращаем дефолт');
return { name: 'Guest' }; // Цепочка продолжается
})
.then(data => {
console.log('Данные:', data); // Выполнится даже при ошибке выше
});
Глобальная обработка ошибок
Для продакшена обязательно настройте глобальные перехватчики. В браузере это window.onerror и window.onunhandledrejection.
window.addEventListener('unhandledrejection', event => {
event.preventDefault(); // Чтобы не шумело в консоли
console.error('Необработанная Promise ошибка:', event.reason);
// Отправка отчета на сервер мониторинга
});
Всегда завершайте цепочки промисов блоком .catch() или оборачивайте await в try/catch. «Проглоченные» ошибки — главная причина нестабильности JS-приложений.