Когда генерируются асинхронные методы и как вы их ловите?
Из документа узла:
Несколько обычно асинхронных методов в API Node.js могут по- прежнему использовать механизм throw для вызова исключений, которые должны быть обработаны с помощью try / catch. Нет исчерпывающего списка таких методов; пожалуйста, обратитесь к документации каждого метода, чтобы определить подходящий механизм обработки ошибок.
Может кто-нибудь привести пример такой функции, которая асинхронна и до сих пор кидает? Как и когда вы поймаете исключение тогда?
В частности. Они относятся к такой функции:
try
{
obj.someAsync("param", function(data){
console.log(data);
});
}catch(e)
{
}
Обычно я знаю, что выше не имеет смысла, потому что, когда выполняется обратный вызов, try
блок, возможно, уже вышел.
- Но к какому примеру относится отрывок из документации? Если асинхронный метод выдает, как они говорят, где, когда и как я должен справиться с этим? (или, может быть, если вы показываете такую функцию, можете ли вы показать, где в ее документе написано, как обращаться с ней, как указано в цитате?)
2 ответа
Асинхронные методы, подобные приведенному в вашем примере, обычно выдают ошибки программиста, такие как неверные параметры, и вызывают обратный вызов с ошибкой для операционных ошибок.
Но в ES2017 есть и асинхронные функции (объявленные с async function
) и эти ошибки сигнализируют об отклонении обещания, которое они возвращают, что превращается в выбрасываемое исключение при использовании их с await
ключевое слово.
Примеры:
function x(arg, cb) {
if (!arg) throw new Error('Programmer error: bad arguments');
setTimeout(() => {
cb(new Error('Operational error: something bad happened'));
}, 2000);
}
Теперь, когда вы используете его, вы обычно не хотите обрабатывать ошибки программиста - вы хотите их исправить. Таким образом, вы не делаете это:
try {
x();
} catch (err) {
// Why should I handle the case of bad invocation
// instead of fixing it?
}
И операционные ошибки, которые вы обрабатываете так:
x(function (err) {
if (err) {
// handle error
} else {
// success
}
});
Теперь, если у вас есть функция, которая не принимает обратный вызов, но возвращает обещание:
function y() {
return new Promise((res, rej) => setTimeout(() => rej('error'), 2000));
}
Затем вы обрабатываете ошибку следующим образом:
y().catch(error => {
// handle error
});
или при использовании await
:
try {
await y();
} catch (err) {
// handle error
}
Для получения дополнительной информации о разнице между операционными ошибками и ошибками программиста см.:
Для получения дополнительной информации об обещаниях и async
/await
см ссылки в этом ответе.
afaik есть три способа, которыми асинхронная функция может "выбросить"; и как поймать каждого из них:
- как и любая другая функция (иначе кто-то напутал): я не поймал бы эти случаи, потому что их не должно быть в моем коде, а обнаружение таких ошибок затрудняет их поиск и исправление.
function foo(){
//someone messed up, better fixing than catching this
return new Prooooooooooomise((resolve) => 42);
}
try {
foo();
}catch(err){
console.error(err);
}
- Обещания:
function foo(){ return Promise.resolve('bar') }
foo().then(value => value =========> 'error')
.catch(err => {
console.error(err);
return "fixedValue";
});
- И Синтаксис / шаблон обратного вызова узлов:
function foo(value, callback){
setTimeout(function(){
if(Math.random() < .5){
callback("I don't like to", undefined);
}else{
callback(null, value * 2);
}
}, 500);
}
foo(21, function(err, data){
if(err){
//no try..catch at all
console.error(err);
}else{
//do whatever with data
}
})
Это наиболее распространенные асинхронные ошибки, с которыми вы столкнетесь; Ну, первый из них - просто ошибка в асинхронном режиме.