Обработка ошибок
↑ 1.4 JavaScript: основы · ← Предыдущая · → Следующая
Зачем это на собесе
Как правильно бросать и ловить ошибки, особенно в асинхронном коде и на уровне приложения.
Объяснение
try {
const data = JSON.parse(text);
await save(data);
} catch (err) {
if (err instanceof SyntaxError) showMessage("Некорректный JSON");
else throw err; // неизвестное — пробрасываем
} finally {
hideLoader(); // выполняется всегда
}
class ApiError extends Error {
constructor(message, { status, code, cause } = {}) {
super(message, { cause });
this.name = "ApiError"; this.status = status; this.code = code;
}
}
throw new ApiError("Не найдено", { status: 404 });| Тип | Причина |
|---|---|
Error | базовый |
TypeError | неверный тип/undefined.x |
ReferenceError | необъявленная переменная |
SyntaxError | синтаксис, JSON.parse |
RangeError | значение вне диапазона, переполнение стека |
AggregateError | несколько ошибок (Promise.any) |
Асинхронные ошибки:
- В Promise —
.catch()илиtry/await/catch. try/catchне ловит ошибки внутри асинхронных коллбэковsetTimeout.- Глобальные:
window.onerror,window.addEventListener("unhandledrejection", …).
window.addEventListener("unhandledrejection", (e) => report(e.reason));
const results = await Promise.allSettled(tasks); // не падает из-за одной ошибкиПрактики: единая обработка ошибок HTTP (интерсептор), понятные сообщения пользователю, логирование (Sentry) с контекстом, cause для цепочки причин, не глотать ошибки (catch {}), не использовать исключения для обычного потока.
Во Vue: errorCaptured, app.config.errorHandler; ErrorBoundary-подобные компоненты.
Нюансы и подводные камни
throwстроки/объектов — плохо: теряется стек; бросайтеError.fetchне бросает ошибку на 4xx/5xx.finallyсreturnпереопределяет результат.- Без
awaitвнутриtryпромис не будет пойман. - Слишком общий
catchскрывает баги.
Практика
- Создайте иерархию ошибок API и единый обработчик.
- Настройте глобальные обработчики и отправку в Sentry.
- Обработайте
Promise.allSettledс частичными ошибками.
Вопросы с ответами
Ловит ли
try/catchошибки вsetTimeout?Нет: коллбэк выполняется позже; обработку нужно ставить внутри коллбэка.
Как поймать необработанные ошибки промисов?
Событие
unhandledrejectionи.catchна цепочках.