我有一个异步函数,我希望在失败时抛出异常。然而,似乎有一些东西阻止了这一点:
通过省略try catch块,我希望抛出一个异常,我想在函数外部处理这个异常。
我得到的实际结果有点令人困惑:
(节点:10636)未处理的Promiser弹出警告:未处理的promise拒绝(拒绝id:1):E11000重复键错误索引。
(node: 10636)DeprecationWarning:未处理的promise拒绝已弃用。将来,未处理的promise拒绝将使用非零退出代码终止Node.js进程。
async f(obj) {
await db.collection('...').save(obj);
}
当我尝试捕获异常并抛出其他东西时,会得到相同的结果:
async f(obj) {
try {
await db.collection('...').save(obj);
} catch(e) {
throw e.message;
}
}
该函数是从try块调用的,因此看不到这如何是未处理的promise。
我正在尝试使用< code>f作为另一个函数的参数:
g(obj, handler) {
try {
handler(obj);
} catch(e);
...
}
}
g(objToSave, f);
async f(obj) {
try {
await db.collection('...').save(obj);
} catch(e) {
throw e.message;
}
}
该函数是从try块调用的,因此看不到这如何是未处理的promise。
这里未处理的是对由< code>f()函数返回的promise的拒绝,而不是由< code >返回的promise。save()方法。所以这不会导致问题:
async f(obj) {
try {
await db.collection('...').save(obj);
} catch(e) {
console.error(e.message);
}
}
在异步函数中引发异常总是拒绝该函数返回的promise。
要捕获异常,您必须在另一个异步函数中执行此操作:
try {
asyncFunc();
} catch (err) {
// you have the error here
}
或者,您可以显式添加拒绝处理程序:
asyncFunc().catch(err => {
// you have the error here
});
如果您捕获异常并抛出另一个异常,那么您会遇到相同的问题,只是在不同的函数中。
您必须添加一个promise拒绝处理程序,并且不抛出异常或返回被拒绝的promise——或者在另一个处理异常的异步函数中运行该函数,而不是重新抛出相同或新的异常。
总而言之:每个<code>异步
拒绝处理程序是使用双函数. then()
或. catch()
或try{wait asyncFunction();}catch(err){…}
添加的
当您在没有拒绝处理程序的情况下拒绝promise时,您将在旧版本的Node中收到警告,在新版本的Node中收到致命错误-有关更多详细信息,请参阅此答案:
最终,您要做的是在同步函数g
中调用异步函数f
,这将不起作用(这相当于能够将异步函数转换为同步函数)。
相反,g
要么也必须是async
,要么它应该正确处理f
返回的Promise。但是,在本评论中,您声明f
表示的函数可能并不总是返回Promise,在这种情况下,前一个选项最容易实现:
async g(obj, handler) {
return await handler(obj);
}
如果处理程序
不返回promise,而只返回一个值(此处已记录),这也将起作用。
调用< code>g(再次)需要异步函数或代码来处理其返回的promise:
g(objToSave, f).then(...).catch(...)
我想在函数之外处理它
这是你唯一忘记做的事情(这就是为什么警告抱怨未经处理的拒绝)。您的函数 f
工作正常。
您无法从异步函数
中引发同步异常,一切都是异步的,异常将导致结果promise被拒绝。这就是您需要捕获的内容:
function g(obj, handler) {
try {
Promise.resolve(handler(obj)).catch(e => {
console.error("asynchronous rejection", e);
});
} catch(e) {
console.error("synchronous exception", e);
}
}
// or just
async function g(obj, handler) {
try {
await handler(obj);
// ^^^^^
} catch(e) {
console.error("error", e);
}
}
g(objToSave, f);