Почему ошибку в промисе лучше обрабатывать через catch, а не через console.error?
Что проверяют
Понимаете ли вы разницу между логированием и обработкой. console.error печатает сообщение, но отклонённый промис остаётся отклонённым, и остальной код продолжает жить так, будто ошибки не было.
Как отвечать
.catch возвращает новый промис и по умолчанию переводит цепочку обратно в успешное состояние, поэтому именно в нём вы решаете, что делать дальше: подставить запасное значение, показать сообщение, пробросить ошибку выше через throw. Вывод в консоль не делает ни того, ни другого.
fetch(url)
.then((r) => r.json())
.catch((e) => {
report(e);
return fallback;
});Что стоит добавить:
- необработанное отклонение уходит в событие
unhandledrejectionв браузере, а в Node начиная с пятнадцатой версии по умолчанию роняет процесс; - второй аргумент
thenне поймает ошибку, брошенную в его же первом аргументе, а.catchв конце цепочки поймает; catchбезthrowэто проглоченная ошибка: вызывающий код получит успешный промис и пойдёт дальше с пустыми данными;- в
async/awaitту же роль играетtry/catch, аfinallyнужен, чтобы снять индикатор загрузки в обоих исходах.
Где спотыкаются
Ставят .catch ради галочки и внутри только логируют. Снаружи это ровно то же самое, что console.error: состояние ошибки никуда не записали, и пользователь смотрит на вечный индикатор загрузки.
Забывают, что fetch не отклоняется на кодах 404 и 500. Отклонение будет только на сетевом сбое, поэтому response.ok проверяют руками, иначе ветка с обработкой ошибки не выполнится никогда.
Вешают один catch на Promise.all и теряют остальные результаты: первое же отклонение обрывает всё. Когда важен исход каждой операции, берут Promise.allSettled и разбирают статусы по отдельности.