Gernar
JavaScript: асинхронность

Куда пойдет результат упавшего Promise после catch

Разбор вопроса «Куда пойдет результат упавшего Promise после catch» для Frontend Developer: что проверяет интервьюер, ключевые тезисы, практические примеры и частые ошибки.

Вопрос

Куда пойдет результат упавшего Promise после catch

Профессия

Frontend Developer

Что хочет услышать интервьюер

Интервьюер хочет убедиться, что кандидат понимает механизм обработки ошибок в Promise и знает, как работает цепочка then/catch. Важно показать, что catch не завершает цепочку, а преобразует ошибку в успешное выполнение, если не было нового исключения.

Ключевые тезисы

  • После обработки ошибки в catch, Promise переходит в состояние 'fulfilled', если catch не выбросит новую ошибку.
  • Результат выполнения блока catch становится новым значением Promise и может быть обработан в последующих then.
  • Если catch выбросит ошибку (или вернет rejected Promise), цепочка перейдет в состояние 'rejected', и ошибка будет передана следующему обработчику catch.

Подробный ответ

Когда Promise завершается с ошибкой (rejected), управление передается ближайшему обработчику catch в цепочке. Важно понимать, что catch не просто перехватывает ошибку, но и возвращает новый Promise, который может быть либо fulfilled, либо rejected, в зависимости от действий внутри catch. Если catch возвращает значение (или не возвращает ничего, что эквивалентно return undefined), то следующий then получит это значение. Если catch выбрасывает ошибку (или возвращает rejected Promise), то следующий catch в цепочке перехватит эту ошибку.

Пример: если в catch произвести return 'recovery', то следующий then получит 'recovery'. Если в catch произвести throw new Error('fail'), то следующий catch перехватит эту ошибку.

Это поведение позволяет создавать цепочки восстановления после ошибок или каскадные обработчики ошибок. Ключевая идея: catch преобразует rejected Promise в новый Promise, чье состояние зависит от его содержимого.

Практические примеры

Пример 1

Пример 1: Восстановление после ошибки

fetch('url')

.then(response => { throw new Error('Fail') })
  .catch(err => { return 'fallback data' }) // возвращаем значение
  .then(data => console.log(data)) // выведет 'fallback data'

Пример 2

Пример 2: Проброс ошибки дальше

fetch('url')

.then(response => { throw new Error('Fail') })
  .catch(err => { throw new Error('New error') }) // пробрасываем новую ошибку
  .catch(err => console.log(err)) // перехватывает 'New error'

Пример 3

Пример 3: Отсутствие catch (необработанная ошибка)

fetch('url')

.then(response => { throw new Error('Fail') })
  .then(data => console.log(data)) // этот then не выполнится

// В консоли будет UnhandledPromiseRejectionWarning

Частые ошибки

  • Забывают, что catch возвращает Promise, и пытаются использовать его результат без then
  • Путают последовательность then/catch, думая что catch всегда должен быть в конце цепочки
  • Не учитывают, что возврат значения из catch переводит цепочку в состояние fulfilled

Связанные темы

  • Цепочки Promise (Promise chaining)
  • Обработка ошибок в асинхронных функциях (async/await)
  • Глобальные обработчики не пойманных ошибок (unhandledRejection)

Follow-up вопросы

Что произойдет, если после catch добавить еще один then?

Уровень: basic

Если catch успешно обработал ошибку, следующий then получит результат выполнения catch и продолжит цепочку. Если catch выбросил ошибку, следующий then будет пропущен, и управление передастся следующему catch.

Можно ли вернуть новый Promise из catch?

Уровень: intermediate

Да, можно вернуть новый Promise из catch. Если этот Promise завершится успешно (fulfilled), цепочка продолжит выполнение с then. Если он завершится с ошибкой (rejected), управление передастся следующему catch.

Что произойдет, если catch вернет значение, а не новый Promise?

Уровень: basic

Если catch вернет обычное значение (не Promise), оно будет передано в следующий then как успешный результат, и цепочка продолжит выполнение.

Как обработать ошибку, если catch отсутствует в цепочке?

Уровень: basic

Если catch отсутствует, ошибка будет передана в ближайший catch в цепочке или приведет к необработанной ошибке (unhandled rejection), если обработчиков нет.

Как можно предотвратить необработанные ошибки в Promise?

Уровень: intermediate

Чтобы предотвратить необработанные ошибки, всегда добавляйте catch в конце цепочки Promise для обработки любых ошибок, которые могут возникнуть в процессе выполнения.

Содержание