关于javascript:使用异步/等待时在Express中捕获未处理的异常

Catching unhandled exceptions in Express when using async/await

关于以下TypeScript代码:

1
2
3
4
5
6
7
8
9
10
11
app.get('/test_feature', function (req: Request, res: Response) {
    throw new Error("This is the bug");
});

app.use(logErrors);

function logErrors (err: Error, req: Request, res: Response, next: NextFunction) {
    console.log(err);
    mongoDal.log(err.message, err);
    next(err);
}

在这里,我在请求处理程序中引发了一个错误,并按预期触发了logErrors函数。

但是,然后,我更改代码以使用异步功能:

1
2
3
4
app.get('/test_feature', async function (req: Request, res: Response) {
    throw new Error("This is the bug");
    await someAsyncFunction();
});

现在,由于我的函数是异步的,因此错误以某种方式由Express的默认错误处理程序处理,因此无法达到我的自定义错误处理程序,也没有到达Node的默认错误处理程序:

1
2
3
4
5
6
7
8
process.on('uncaughtException', function (err: Error) {
    try {
        console.log(err);
        mongoDal.log(err.message, err);
    } catch (err) {

    }
});

当异步函数中发生错误时,如何使我的\\'logErrors \\'函数到达?我想要一个通用的解决方案,而不是尝试/捕获每个请求处理程序。


这里的问题是您的处理程序根本不再引发同步异常。取而代之的是,您的处理程序返回一个承诺,但该承诺被拒绝。请注意,这不是承诺或异步/等待特定的问题,对于使用回调等的任何快速代码来说,这也是一个普遍的问题-如果您在编写异步代码时没有在所有地方仔细处理错误,则很容易将其完全丢失。

要在您的情况下处理此问题,需要注册一些内容以捕获对您返回的承诺的拒绝。有几种选择:

  • 将.catch()显式添加到所有错误处理程序中,然后自己处理错误,或通过调用next(err)委派给常规的快速错误处理。
  • 为您的处理程序创建一个包装函数以执行此操作,并在所有地方使用它。您可以为此使用现有的wrap()函数,例如express-promise-wrap。
  • 扩展.get和朋友可以自动跟踪处理程序返回的诺言中的拒绝。您可以手动执行此操作,但看起来像承诺的那样是此的有效实现(尽管我没有尝试过)。
  • 设置起来有点复杂,但是在我看来,最好设置为3。这样,您应该能够将异步函数作为处理程序编写,它们都将在后台返回承诺,并且您的处理程序代码将自动监视这些承诺是否发生任何后续失败。

    StrongLoop实际上有一篇文章更全面地介绍了这一点,如果您想进一步阅读的话:https://strongloop.com/strongblog/async-error-handling-expressjs-es7-promises-generators/