Как catch влияет на цепочку промисов в JavaScript
Что проверяют
Понимаете ли вы, что catch не завершает цепочку, а возвращает новый промис, и от того, что вернёт обработчик, зависит, пойдёт цепочка дальше успешно или с ошибкой. Следом часто дают кусок кода и просят сказать, что выведется и в каком порядке.
Как отвечать
Начните с того, что p.catch(fn) это то же самое, что p.then(undefined, fn). Отсюда всё поведение:
- что ловит: ошибку исходного промиса и любого
thenвыше по цепочке, будь тоthrowили возврат отклонённого промиса. То, что стоит ниже, он не видит; - вернул значение: цепочка «вылечена», следующий
thenполучает это значение. Ничего не вернул, значит следующийthenполучитundefined, но всё равно выполнится; - бросил ошибку или вернул
Promise.reject(): цепочка остаётся отклонённой, управление уходит к следующемуcatch; then(ok, fail)противthen(ok).catch(fail): во втором варианте ошибка, брошенная внутриok, будет поймана, в первом нет;finally: не получает аргумента и пропускает значение или ошибку дальше без изменений, если сам не бросил исключение.
Отдельно скажите про необработанные отклонения: в браузере срабатывает событие unhandledrejection, в Node.js по умолчанию процесс завершается. С async/await та же логика записывается через try/catch, но есть ловушка: return promise внутри try без await отдаёт промис наружу, и ваш catch его ошибку не поймает, нужен return await.
Практическое правило: промежуточный catch ставят, только если есть осмысленное значение по умолчанию. Иначе ошибку ловят в одном месте, ближе к UI, где можно показать сообщение пользователю.
Где спотыкаются
Утверждают, что после catch следующие then не выполняются. Выполняются, если обработчик не бросил ошибку заново.
Ставят catch в середину цепочки ради логирования и забывают сделать throw err. Ошибка проглатывается, а следующий шаг падает на undefined уже с непонятным TypeError.
Забывают return внутри then. Вложенный промис отрывается от цепочки, его ошибка до catch не доходит и всплывает как необработанная.