Как перехватить исключение в JavaScript
Что проверяют
Понимаете ли вы, какие ошибки try...catch ловит, а какие пролетают мимо: асинхронные колбэки, промисы без await, ошибки в обработчиках React. Следом почти всегда спрашивают, как не потерять ошибку в продакшене.
Как отвечать
Базовая конструкция: try с опасным кодом, catch (err) с обработкой, finally для того, что выполнится в любом случае (снять лоадер, закрыть соединение). С ES2019 переменную можно опустить: catch { ... }.
Дальше покажите, что понимаете детали:
- что бросают:
throwпринимает что угодно, поэтому вcatchсначала проверяютerr instanceof Errorили конкретный класс. Свои классы наследуют отError, а исходную ошибку передают черезnew Error("...", { cause: err }); - асинхронность:
tryвокругsetTimeoutилиaddEventListenerне поймает ошибку внутри колбэка, к моменту её появления стек уже другой. Для промисов нуженawaitвнутриtryили.catch(); - fetch: промис отклоняется только при сетевой ошибке. Ответ 404 или 500 это успешный промис, статус проверяют через
response.ok; - глобальные ловушки: событие
errorнаwindowиunhandledrejectionдля промисов без обработчика. Сюда подключают Sentry или свой сбор ошибок; - React: Error Boundary ловит ошибки рендера и методов жизненного цикла, но не ошибки в обработчиках событий и асинхронном коде, их обрабатывают
try...catchна месте.
Закончите тем, что делать в catch: либо восстановиться (повторить запрос, показать запасной интерфейс), либо пробросить ошибку дальше через throw, дописав контекст. Молча залогировать и продолжить хуже обоих вариантов.
Где спотыкаются
Пишут пустой catch или только console.log. Ошибка исчезает, а баг потом ищут неделю.
Внутри try возвращают промис без await: return fetchData(). Отклонение уходит наружу, catch его не видит.
Считают, что Error Boundary закрывает все ошибки приложения, и не ставят обработку в onClick и вокруг запросов.