【问题标题】:When do async methods throw and how do you catch them?异步方法何时抛出以及如何捕获它们?
【发布时间】:2017-07-01 09:07:45
【问题描述】:

来自节点doc

Node.js API 中的一些典型的异步方法可能 仍然使用 throw 机制来引发必须处理的异常 使用尝试/捕捉。没有此类方法的完整列表; 请参阅每种方法的文档以确定 需要适当的错误处理机制。

有人能举出这样一个异步但仍然抛出的函数的例子吗?那么,您如何以及何时捕获异常?

更具体地说。他们是否引用了这样的功能:

try
{

   obj.someAsync("param", function(data){
                    console.log(data);
                 });
}catch(e)
{

}

现在我通常知道上面没有意义 - 因为当回调执行时,try 块可能已经退出。

  • 但是文档摘录是指什么样的示例?如果异步方法如他们所说的那样抛出,我应该在哪里、何时以及如何处理它? (或者,如果您展示了这样的功能,您能否在其文档中说明如何处理它,如报价中所述?)

【问题讨论】:

  • 你能举一个这样的功能的例子,我可以试试..
  • @AbhinavGauniyal 好吧,如果您仔细查看问题,我正在寻找该功能(或假设的功能)以及您自己处理它的方式
  • 哦,不知道我是怎么跳过的。通常我看到错误作为 err 参数从父异步函数传递到回调,所以我也很好奇。
  • @AbhinavGauniyal 是的,你可以好好检查一下文档,err 的情况是单独处理的,这个单独处理。
  • @GiorgiMoniava 如果有帮助 - github.com/nodejs/docs/issues/124

标签: javascript node.js exception asynchronous


【解决方案1】:

像您示例中的异步方法通常会抛出错误参数等程序员错误,并且它们会调用带有错误的回调来处理操作错误。

但在 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 的更多信息,请参阅this answer 中的链接。

【讨论】:

  • 如果您要致电dns.lookup({}),就是一个例子。那会抛出。
  • 我正在尝试理解这部分文档 - that must be handled using try / catch,如果您忽略这一点并仍然按照通常的 if (err) { } 语法处理它,那么文档说明它是错误的,或者您没有处理它们正确。 请注意,文档确实有另一部分 if (err) { } 处理错误的方式,这表示这些错误与 try/catch 点不同,这会造成混乱。
  • @rsp:如果我需要使用您的示例中的 first 函数x,我是否理解正确,我都需要将它包含在 try/catch 中并检查回调内部出错?
  • @GiorgiMoniava 实际上取决于。要使用我的第一个函数x(),只有当您需要处理使用错误参数调用x() 函数的程序员错误时,您才需要同时执行这两项操作,但如果您希望此错误停止您的程序以便您可以注意到它并修复然后你不想在那里尝试/捕捉,你应该只在回调中检查err,因为这是一个操作错误,即使程序正确也可能发生(比如失去与数据库的连接或类似的东西那),没有什么可以解决的。请参阅我的答案中有关处理错误的文章以了解基本原理
【解决方案2】:

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
}
})

这些是您会遇到的最常见的异步错误;好吧,第一个只是异步方法中的一个普通错误。

【讨论】:

  • 公平地说,也不是第二名。那个捕捉电话是为了承诺,文档明确说明 - exceptions that must be handled using try / catch
  • @AbhinavGauniyal 那又怎样?你说你不能捕获异步错误是因为处理它们的工具不包含 try..catch 块吗?
  • @Thomas 请阅读例外情况,然后提出此类问题。
猜你喜欢
  • 2010-12-25
  • 2020-09-28
  • 1970-01-01
  • 1970-01-01
  • 2020-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-02
相关资源
最近更新 更多