try-catch не ловит ошибку
Описание
Написал простое допорлнение:
declare global {
interface Promise<T> {
isFulfilled: Promise<boolean>;
}
}
Object.defineProperty(Promise.prototype, "isFulfilled", {
async get<T>(this: Promise<T>): Promise<boolean> {
const symbol = Promise.resolve(Symbol());
try {
const result = (await Promise.race([this, symbol]) !== symbol);
console.log("after promise");
return result;
} catch {
console.log(`catch`);
return true;
}
}
});
const promise = new Promise<void>(async (resolve) => {
throw new Error(`Test error`);
});
console.log(await (promise.isFulfilled));
export { };
Как видим выполнение Promise-а происходит в try и не выходит за него. В таком случае при ошибке try должен его ловить и перейти к catch.
Я и получаю ошибку и продолжается выполнение try:
Вопрос
Почему так происходит?
Как исправить мою функцию.
Ответы (1 шт):
Тут, наверно, правильнее было бы назвать isSettled, если судить по коду. Fulfilled - это когда промис завершен успешно, а у тебя проверяется, что он в принципе завершен, т.е. не pending. Но это смотри сам.
Ошибки сразу в нескольких местах. Во первых, непонятно зачем надо было резолвить симбол. Теперь там промис, и сравнение "!== symbol" всегда будет true.
Во вторых, тестовый пример. В конструктор промиса передана async-функция. В итоге она сама закетчила исключение и вернула отклоненный промис, который не был обработан и потому вывалил ошибку в консоль. А тот промис, который ты создал через конструктор, навсегда остался пендингом, ведь в переданной в конструктор функции не было необработанного исключения (и функции resolve/reject никто не вызвал). Далее в isFulfilled race вернул симбол, который, как и было сказано выше, не равен промису с симболом. Итого true вместо false.
Исправленный вариант для isFulfilled и тестовые примеры:
Object.defineProperty(Promise.prototype, "isFulfilled", {
get() {
const s = Symbol();
return Promise.race([this, s]).then(v => v !== s, () => true);
}
});
Promise.resolve().isFulfilled.then(console.log); // true
Promise.reject().isFulfilled.then(console.log); // true
new Promise(() => {}).isFulfilled.then(console.log); // false
new Promise((res) => {
setTimeout(res, 100)
}).isFulfilled.then(console.log); // false
new Promise(() => {
throw new Error('err');
}).isFulfilled.then(console.log); // true
new Promise((res) => {res();}).isFulfilled.then(console.log); // true
