[英]Express error handling and async await
In my Node.js app I added the following code to catch every uncaught exception: 在我的Node.js应用程序中,我添加了以下代码来捕获每个未捕获的异常:
process.on('uncaughtException', function (err: Error) {
try {
logger.err(err);
} catch (err) {
}
});
The problem is that Express has its own default error handler, which catches every uncaught exception. 问题是Express有自己的默认错误处理程序,它捕获每个未捕获的异常。 Now, Express caught the exceptions before Node (process.on), so my logger didn't get reached.
现在,Express在Node(process.on)之前捕获了异常,因此我的记录器没有到达。 However, it's possible to add another error handler that can catch every exception before Express does:
但是,可以在Express之前添加另一个可以捕获每个异常的错误处理程序:
app.use(logErrors);
function logErrors (err: Error, req: Request, res: Response, next: NextFunction) {
logger.err(err);
next(err);
}
This still doesn't cover every case. 这仍然不包括每一个案例。 Whenever I have an
async function
that I call with await
, there's no exception, but a rejected Promise is returned instead. 每当我有一个我用
await
调用的async function
,没有异常,但是返回了被拒绝的Promise。 For example: 例如:
app.get('/foo', async function (req: Request, res: Response, next: NextFunction) {
await bar();
});
function bar() {
throw new Exception();
}
won't reach my logErrors
function because it won't throw, but will return a rejected Promise. 将无法访问我的
logErrors
函数,因为它不会抛出,但会返回被拒绝的Promise。
So to fix it, I wrapped my Express HTTP handlers with another function: 所以为了修复它,我用另一个函数包装了我的Express HTTP处理程序:
app.get('/foo', wrap(async function (req: Request, res: Response, next: NextFunction) {
await bar();
}));
function wrap(func: (req: Request, res: Response, next: NextFunction) => void) {
return async function (req: Request, res: Response, next: NextFunction) {
try {
await func(req, res, next);
}
catch (err) {
next(err);
}
}
}
next(err) passes the error to my handler. next(错误)将错误传递给我的处理程序。 Now, I manage to catch the exceptions to my
logErrors
function. 现在,我设法捕获我的
logErrors
函数的异常。
I'm almost done. 我就快完成了。 I still have one case in which I can't catch the errors.
我还有一个案例,我无法发现错误。 It happens when I call an
async function
without the await
keyword (It's sometimes useful to use the same function in two different places in the code, once calling in asynchronously, and once synchronously). 当我在没有
await
关键字的情况下调用async function
时会发生这种情况(有时在代码中的两个不同位置使用相同的函数,一次异步调用,并且一次同步调用)。 So this code won't catch the error: 所以这段代码不会捕获错误:
app.get('/foo', wrap(async function (req: Request, res: Response, next: NextFunction) {
bar();
}));
What's happening here is that the Express HTTP handler returns a resolved Promise to the wrap
function. 这里发生的是Express HTTP处理程序将已解析的Promise返回给
wrap
函数。 The wrap function in turn, does not reach the catch
block, so it does not call to next(err)
which would reach my logger. 依次包装函数没有到达
catch
块,所以它不会调用next(err)
来到我的记录器。
bar
function in turn, returns a rejected Promise, but there is no one waiting for its return value. bar
函数反过来,返回一个被拒绝的Promise,但是没有人等待它的返回值。
How can I change my code in such a way I won't end up with any unhandled Promise rejection? 如何以这样的方式更改我的代码我不会以任何未处理的Promise拒绝结束? (only generic solution)
(只有通用解决方案)
There is another process.on
event you can set up a listener for - unhandledRejection . 还有另一个
process.on
事件,你可以为 - unhandledRejection设置一个监听器。
You can use it to handle those rejections all over the code. 您可以使用它来处理整个代码中的拒绝。
NOTE : remember to terminate your process after you logged everything you needed. 注意 :记住在记录所需内容后终止进程。 More on this here .
更多关于这里 。
I've found a solution: 我找到了一个解决方案:
app.get('/foo', async function (req: Request, res: Response, next: NextFunction) {
dontAwait(() => bar());
});
async function dontAwait(func: () => void) {
try {
await func();
}
catch (err) {
logErrors(err);
}
}
I still have one case in which I can't catch the errors.
我还有一个案例,我无法发现错误。
You could, but you currently simply don't do anything with the result. 你可以,但你目前根本没有对结果做任何事情。 If you want your usual error handlers to trigger, you need to
await
it. 如果您希望触发通常的错误处理程序,则需要
await
它。
It happens when I call an
async function
without theawait
keyword当我在没有
await
关键字的情况下调用async function
时会发生这种情况
I can't see any good reason for that. 我看不出有什么好的理由。 But if you really want to fire and forget the function , you can do it.
但是如果你真的想解雇并忘记这个功能 ,你就可以做到。 You just have to handle errors explicitly:
您只需要明确处理错误:
bar().catch(e => logger.err(e));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.