Можно ли делать несколько then/catch подряд после промиса
Что проверяют
Знаете ли вы, что каждый then возвращает новый промис, и как по такой цепочке идут значения и ошибки. Следом почти всегда дают кусок кода с catch посередине цепочки и просят сказать, что выведется.
Как отвечать
Да, можно, это обычная практика. Ключевые правила:
- новый промис на каждом шаге:
thenиcatchвозвращают новый промис, который резолвится тем, что вернул колбэк. Вернули промис, и следующий шаг дождётся его результата; catchэтоthen(undefined, onRejected): он ловит ошибку любого шага выше по цепочке, а сам возвращает успешный промис. Поэтому послеcatchцепочка продолжается, и следующийthenполучит то, что вернул обработчик, илиundefined;- проброс ошибки: если в
catchнужно только залогировать, а не погасить ошибку, делаютthrow err, и её поймает следующийcatch; - второй аргумент
then:then(ok, fail)не ловит исключение, брошенное в самомok. Для этого нужен отдельныйcatchниже; finally: не получает значения и пропускает результат дальше без изменений, если сам не бросит ошибку.
Стоит различать цепочку и ветвление. p.then(a).then(b) выполняет шаги последовательно, а p.then(a); p.then(b); вешает на один промис два независимых обработчика, и оба получат одно и то же значение. Колбэки выполняются микрозадачами, то есть после текущего синхронного кода, но раньше setTimeout.
В конце можно показать тот же сценарий на async/await с try/catch: логика та же, читается проще.
Где спотыкаются
Забывают return внутри then. Асинхронная операция запускается, но цепочка её не ждёт, и следующий шаг получает undefined.
Ставят catch в середину и думают, что после него цепочка оборвётся. На деле она продолжится успешно, и дальше код работает с пустым значением.
Путают ветвление с цепочкой и не вешают catch на каждую ветку. Отклонение в ветке без обработчика даёт в браузере unhandledrejection.