Улавливание ошибок в JavaScript Promises с помощью первого уровня try... catch
Итак, я хочу, чтобы мой захват первого уровня был тем, который обрабатывает ошибку. Есть ли способ распространять мою ошибку до этого первого улова?
Код ссылки, не работает (пока):
Promise = require('./framework/libraries/bluebird.js');
function promise() {
var promise = new Promise(function(resolve, reject) {
throw('Oh no!');
});
promise.catch(function(error) {
throw(error);
});
}
try {
promise();
}
// I WANT THIS CATCH TO CATCH THE ERROR THROWN IN THE PROMISE
catch(error) {
console.log('Caught!', error);
}
Ответы
Ответ 1
С помощью нового синтаксиса async/await вы можете достичь этого. Обратите внимание, что на момент написания это не поддерживается всеми браузерами, вам, вероятно, нужно перевести код babel (или что-то подобное).
// Because of the "async" keyword here, calling getSomeValue()
// will return a promise.
async function getSomeValue() {
if (somethingIsNotOk) {
throw new Error('uh oh');
} else {
return 'Yay!';
}
}
async function() {
try {
// "await" will wait for the promise to resolve or reject
// if it rejects, an error will be thrown, which you can
// catch with a regular try/catch block
const someValue = await getSomeValue();
doSomethingWith(someValue);
} catch (error) {
console.error(error);
}
}
Ответ 2
Вы не можете использовать команды try-catch для обработки исключений, созданных асинхронно, поскольку функция "возвращает" до того, как будет выбрано любое исключение. Вместо этого вы должны использовать методы promise.then
и promise.catch
, которые представляют асинхронный эквивалент оператора try-catch.
Что вам нужно сделать, так это вернуть обещание, а затем связать с ним еще один .catch
:
function promise() {
var promise = new Promise(function(resolve, reject) {
throw('Oh no!');
});
return promise.catch(function(error) {
throw(error);
});
}
promise().catch(function(error) {
console.log('Caught!', error);
});
Promises являются цепями, поэтому, если обещание повторяет ошибку, оно будет делегировано до следующего .catch
.
Кстати, вам не нужно использовать круглые скобки вокруг операторов throw
(throw a
совпадает с throw(a)
).
Если вы используете этот код в Node.js, и по какой-то причине вам не разрешено редактировать функцию promise
, вы можете использовать домены для этого. Обратите внимание, что домены - это не самые простые вещи, с которыми приходится иметь дело, и в некоторых случаях имеют некоторые досадные краевые случаи. Если вам это действительно нужно, я бы рекомендовал вместо этого использовать promises.
Ответ 3
Нет! Это абсолютно невозможно, так как promises по своей сути асинхронны. Предложение try-catch будет завершено, когда будет выбрано исключение (и путешествие по времени еще не было изобретено).
Вместо этого верните promises из всех ваших функций и зацепите за них обработчик ошибок.
Ответ 4
Я часто нахожу необходимость обеспечить возврат обещания и почти так же часто нужно обрабатывать локальную ошибку, а затем, возможно, повторно ее уничтожить.
function doSomeWork() {
return Promise.try(function() {
return request.get(url).then(function(response) {
// ... do some specific work
});
}).catch(function(err) {
console.log("Some specific work failed", err);
throw err; // IMPORTANT! throw unless you intend to suppress the error
});
}
Преимущество этого метода (Promise.try/catch) заключается в том, что вы запускаете/обеспечиваете цепочку Promise без требования разрешения/отклонения, которое легко можно пропустить и создать кошмар для отладки.
Ответ 5
Чтобы расширить на edo ответ, если вы хотите поймать ошибки async-функции, которую вы не хотите ждать. Вы можете добавить выражение ожидания в конце своей функции.
async function() {
try {
const asyncResult = someAsyncAction();
// "await" will wait for the promise to resolve or reject
// if it rejects, an error will be thrown, which you can
// catch with a regular try/catch block
const someValue = await getSomeValue();
doSomethingWith(someValue);
await asyncResult;
} catch (error) {
console.error(error);
}
}
Если someAsyncAction
не работает, оператор catch будет обрабатывать его.