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

Posted

技术标签:

【中文标题】使用 async/await 时在 Express 中捕获未处理的异常【英文标题】:Catching unhandled exceptions in Express when using async/await 【发布时间】:2017-04-12 12:42:13 【问题描述】:

关于以下 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);

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

然后,我将代码更改为使用异步函数:

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

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

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

    
);

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

【问题讨论】:

【参考方案1】:

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

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

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

设置起来稍微复杂一些,但在我看来,一旦安装到位,3 是最好的选择。有了它,您应该能够将异步函数编写为处理程序,它们都将在后台返回 Promise,并且您的处理程序代码将自动监控这些 Promise 以防任何后续失败。

StrongLoop 实际上有一篇文章对此进行了更详细的讨论,如果您想进一步阅读:https://strongloop.com/strongblog/async-error-handling-expressjs-es7-promises-generators/

【讨论】:

以上是关于使用 async/await 时在 Express 中捕获未处理的异常的主要内容,如果未能解决你的问题,请参考以下文章

Async/await mvc express 使用 .catch() 处理错误的问题

在 express (async/await) 中使用一个 mongoose 查询的输出作为另一个查询的输入

Node/Express 和 MongoDB:Async/Await 与 Model.create()

Express 和 async/await:我应该用 try/catch 包装吗?

使用Mocha / Chai和async / await验证是否抛出异常

如何使用 async/await 查询 MongoDB?