Promise сам перехватывает синхронное исключение executor и превращает его в отклонение. Наружу из конструктора это исключение не выходит, поэтому внешний catch не срабатывает.
Почему внешний try/catch не ловит ошибку, брошенную внутри Promise
Promise сам перехватывает синхронное исключение executor и превращает его в отклонение. Наружу из конструктора это исключение не выходит, поэтому внешний catch не срабатывает.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Разъясните, почему исключение, возникшее внутри тела Promise, не перехватывается внешним блоком try/catch.
try {
new Promise((resolve, reject) => {
throw "asda";
});
} catch (e) {
console.log("Error", e);
}
- Внутри конструктора
Promiseлюбые синхронные ошибки автоматически преобразуются в отклонённый промис, а не пробрасываются наружу как обычные исключения. - Блок
try/catchможет отловить только ошибки, которые выбрасываются синхронно в текущем стеке вызовов. Ошибка, превратившаяся в отклонение промиса, будет обработана только через методы.catch,awaitсtry/catchвнутри асинхронной функции или обработчик отклонения при создании промиса. - Чтобы перехватить такую ошибку, нужно добавить обработчик отклонения:
new Promise((resolve, reject) => {
throw "asda";
}).catch(err => console.log("Caught", err));
или использовать async/await:
(async () => {
try {
await new Promise((resolve, reject) => {
throw "asda";
});
} catch (e) {
console.log("Caught", e);
}
})();
Ответ
Promise сам перехватывает синхронное исключение executor и превращает его в отклонение. Наружу из конструктора это исключение не выходит, поэтому внешний catch не срабатывает.
Это не потому, что executor асинхронный: он выполняется сразу. Изменяется способ передачи ошибки — через состояние Promise. Добавьте .catch(...) либо await внутри try/catch async-функции, как показано в условии. Без обработчика среда сообщит о необработанном отклонении. Лучше бросать Error вместо строки, чтобы сохранить сообщение и стек; исключение из отдельного timer-callback уже не перехватывается конструктором автоматически.