Javascript 如何从异步函数抛出异常
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/42926390/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to throw exception from async function
提问by user1063963
I have an async function that I expect to throw exception on failure. However something seems to preventing this:
我有一个异步函数,我希望在失败时抛出异常。然而,似乎有些事情阻止了这一点:
by omitting the try catch blocks I expect an exception to be thrown which I want to handle outside of the function.
通过省略 try catch 块,我希望抛出一个我想在函数之外处理的异常。
The actual result I get is somewhat confusing:
我得到的实际结果有些令人困惑:
(node:10636) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): E11000 duplicate key error index.
(node:10636) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): E11000 duplicate key error index.
(node:10636) DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
(node:10636) DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
async f(obj) {
await db.collection('...').save(obj);
}
I get the same result when I try to catch the exception and throw something else instead:
当我尝试捕获异常并抛出其他内容时,我得到了相同的结果:
async f(obj) {
try {
await db.collection('...').save(obj);
} catch(e) {
throw e.message;
}
}
The function is called from a try block, so don't see how this is an Unhandled Promise.
该函数是从 try 块中调用的,所以不要看这是一个未处理的 Promise。
I am trying to use fas a parameter of another function:
我试图f用作另一个函数的参数:
g(obj, handler) {
try {
handler(obj);
} catch(e);
...
}
}
g(objToSave, f);
采纳答案by robertklep
Ultimately, what you're trying to do is calling an asynchronous function fin a synchronous function g, which won't work (that would be the equivalent of being able to turn an asynchronous function into a synchronous function).
最终,您要做的是在同步函数f中调用异步函数g,这将不起作用(这相当于能够将异步函数转换为同步函数)。
Instead, geither has to be asyncas well, or it should properly handle the promise returned by f. However, in this commentyou state that the function represented by fmay not always return a promise, in which case the former option would be the easiest to implement:
相反,g要么也必须async如此,要么应该正确处理f. 但是,在此评论中,您声明由 表示的函数f可能并不总是返回承诺,在这种情况下,前一个选项最容易实现:
async g(obj, handler) {
return await handler(obj);
}
This will also work if handlerdoesn't return a promise, but just a value (which is documented here).
如果handler不返回承诺,而只返回一个值(此处记录),这也将起作用。
Calling g(again) requires either an async function, or code to handle its returned promise:
调用g(再次)需要异步函数或代码来处理其返回的承诺:
g(objToSave, f).then(...).catch(...)
回答by rsp
async f(obj) {
try {
await db.collection('...').save(obj);
} catch(e) {
throw e.message;
}
}
The function is called from a try block, so don't see how this is an Unhandled Promise.
该函数是从 try 块中调用的,所以不要看这是一个未处理的 Promise。
What is unhandled here is the rejection of a promise returned by the f()function, not by the .save()method. So this will not cause that problem:
这里未处理的是拒绝f()函数返回的承诺,而不是.save()方法。所以这不会导致这个问题:
async f(obj) {
try {
await db.collection('...').save(obj);
} catch(e) {
console.error(e.message);
}
}
Throwing an exception in async function always rejects the promisethat is returned by that function.
在 async 函数中抛出异常总是拒绝该函数返回的承诺。
To catch the exception you either have to do this in another async function:
要捕获异常,您必须在另一个异步函数中执行此操作:
try {
asyncFunc();
} catch (err) {
// you have the error here
}
or you can add a rejection handler explicitly:
或者您可以显式添加拒绝处理程序:
asyncFunc().catch(err => {
// you have the error here
});
If you are catching the exception and throwing another exception then you get the same problem, just in a different function.
如果您正在捕获异常并抛出另一个异常,那么您会遇到同样的问题,只是在不同的函数中。
You either have to add a promise rejection handler and not throw an exception or return a rejected promise there - or run that function in another async function that handles the exception instead of rethrowing the same or new exception.
您要么必须添加一个承诺拒绝处理程序并且不抛出异常或在那里返回一个被拒绝的承诺 - 或者在另一个处理异常的异步函数中运行该函数,而不是重新抛出相同或新的异常。
To sum it up: Every asyncfunction returns a promise. Every promise needs to have a rejection handler.
总结一下:每个async函数都返回一个promise。每个承诺都需要有一个拒绝处理程序。
The rejection handler is added using a two-function .then()or with .catch(), or with try { await asyncFunction(); } catch (err) { ... }
拒绝处理程序使用两个函数.then()或 with.catch()或 withtry { await asyncFunction(); } catch (err) { ... }
When you have a promise rejection with no rejection handler, you will get a warning in older versions of Node and a fatal error in newer versions of Node - see this answer for more details:
当您有一个没有拒绝处理程序的承诺拒绝时,您将在旧版本的 Node 中收到警告,在较新版本的 Node 中收到致命错误 - 有关更多详细信息,请参阅此答案:
回答by Bergi
which I want to handle outside of the function
我想在函数之外处理
That's the only thing you forgot to do. (Which is why the warning is complaining about an unhandledrejection). Your function fis working fine.
这是你唯一忘记做的事情。(这就是警告抱怨未经处理的拒绝的原因)。您的功能f运行良好。
You cannot throw a synchronous exception from an async function, everything is asynchronous and exceptions will lead to a rejection of the result promise. That is what you will need to catch:
您不能从 an 抛出同步异常async function,一切都是异步的,异常将导致拒绝结果承诺。这就是你需要抓住的:
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);

