使用async/await时在Express中捕获未处理的异常

Alo*_*lon 6 javascript error-handling express async-await typescript

请注意以下TypeScript代码:

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);
}
Run Code Online (Sandbox Code Playgroud)

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

但是,我改变我的代码以使用异步函数:

app.get('/test_feature', async function (req: Request, res: Response) {
    throw new Error("This is the bug");
    await someAsyncFunction();
});
Run Code Online (Sandbox Code Playgroud)

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

process.on('uncaughtException', function (err: Error) {
    try {
        console.log(err);
        mongoDal.log(err.message, err);
    } catch (err) {

    }
});
Run Code Online (Sandbox Code Playgroud)

在异步函数中发生错误时,如何使"logErrors"功能到达?我想要一个通用的解决方案,而不是在每个请求处理程序中尝试/ catch.

Tim*_*rry 6

这里的问题是你的处理程序不再引发同步异常了.相反,您的处理程序返回一个被拒绝的promise.请注意,这不是承诺或异步/等待特定问题,这对于使用回调等的任何快速代码也是一个普遍问题 - 如果在编写异步代码时没有仔细处理错误,则很容易完全丢失它们.

为了在你的情况下处理这个问题,有些东西需要注册以避免你回来的承诺的拒绝.有几个选项:

  1. 明确地向所有错误处理程序添加.catch(),并自己处理错误,或者通过调用next(err)委托正常的快速错误处理.
  2. 为您的处理程序创建一个包装函数来执行此操作,并在任何地方使用它.您可以使用现有的wrap()函数,例如express-promise-wrap.
  3. 扩展.get和朋友自动跟踪处理程序返回的承诺中的拒绝.您可以手动执行此操作,但它看起来像是表达承诺是一个有效的实现(虽然我没有尝试过).

设置起来有点复杂,但是一旦你有了它,我强烈考虑3.有了这个,您应该能够将异步函数编写为处理程序,它们都将在引擎盖下返回承诺,并且您的处理程序代码将自动监视任何后续失败的承诺.

如果你想进一步阅读,StrongLoop实际上已经有一篇文章更详细地看了这篇文章:https://strongloop.com/strongblog/async-error-handling-expressjs-es7-promises-generators/