承诺 - 未处理的拒绝挂起请求

时间:2017-03-12 18:06:05

标签: node.js express promise async-await

我在Node.js中开发了一个后端应用程序,我遇到了以下问题:当开发人员调用promise函数时,如下所示:

mainRouter.get("/xD", async (req, res) => {
    res.send(await this.fooService.foo());
});

this.fooService.foo()函数可能会失败(承诺拒绝),最终用户将获得请求超时。

我想确定开发人员错误不会导致UnhandledPromiseRejectionWarning(最后是超时错误)。问题是如何配置应用程序以记录错误并在发生UnhandleRejection时将状态500返回给用户。

我尝试了什么:

mainRouter.get("/xD", async (req, res) => {
    try {
        res.send(await this.fooService.foo());
    } catch (err) {
        res.status(500).send("error");
    }
});

上面的代码会做的事情,但它要求开发人员在每个路由中编写上面的代码,所以它不是一个干净的解决方案。

我也尝试使用错误中间件:

mainRouter.use((err:any, req, res, next) => {
    console.log(err);
    res.status(500).send("Error");
});

但它没有捕获PromiseRejection

最后,我创建了中间件,为unhandledRecejtion事件注册函数处理程序:

mainRouter.use((req, res, next) => {
    process.on('unhandledRejection', (reason, p) => {
        console.log(reason);
        res.status(500).send("Error");
    });
    next();
});

我不确定进程事件在node.js中是如何工作的,但我担心上面的代码会导致方案出现问题:

  1. 第一个请求会生成未处理的承诺拒绝
  2. 最后注册处理程序的最新请求将返回用户状态500。

1 个答案:

答案 0 :(得分:0)

为什么不提供每个人都可以使用的包装函数

async function wrapAsync(res, asyncFn) {
    try {
        res.send(await asyncFn());
    } catch (err) {
        res.status(500).send("error");
    }
}

其中asyncFn是一个返回promise

的函数

然后其他开发人员可以这样简单地使用它

mainRouter.get("/xD", async (req, res) => await wrapAsync(res, this.fooService.foo));

也可以覆盖mainRouter.get并提供更短的抽象