【问题标题】:Catching all errors in async-await express route handlers捕获 async-await 快速路由处理程序中的所有错误
【发布时间】:2018-10-07 09:47:54
【问题描述】:

假设我有这样的路线:

app.get('/broken', (req, res) => {
  throw new Error('Broken!');
});

这永远不会向客户端发送响应。

但是,我可以为所有错误添加一个中间件:

const errorMiddleware = (error, req, res, next) => {
  if (error) {
    console.error(error);
    return res.status(500)
      .json({
        message: 'Internal server error', 
      });
  }
  next(error);
};

但这不适用于async 路由,因为它们不直接throw。

例如,这将不起作用:

app.get('/broken', async (req, res) => {
  throw new Error('Broken!');
});

所以我可以像这样创建一个包装器:

const asyncRoute = f => (req, res, next) => {
  return Promise.resolve(f(req, res, next)).catch(next);
};

app.get('/broken', asyncRoute(async (req, res) => {
  throw new Error('Broken!');
}));

但这真的很痛苦,因为现在我必须为每条路线调用这个函数!

有什么更好的方法来处理这个问题?


【问题讨论】:

  • 你认为路由回调async 有什么好处? Express 不使用承诺,所以......纯粹是为了在其中获得await 语义吗?如果是这样,您的包装器就是这样做的正确方法。
  • (你可以看看Koa。)
  • 好吧,我的一些路由需要多次 async 调用(例如数据库、API、bcrypt),因此在 async 上下文中更容易编写。
  • @T.J.Crowder 如果我没有通过承诺(例如123),那么我希望强制承诺(例如Promise.resolve(123))。请注意,Promise.resolve(Promise.resolve(x)) 被展平为Promise.resolve(x)。
  • 好的。我没有看到任何理由将非承诺传递给名为asyncRoute 的东西,所以我没有意识到你想要处理这个问题。 :-)

标签: javascript express async-await


【解决方案1】:

基本上,您不想直接将async 函数传递给 Express 的app.get,因为app.get 不处理函数返回的承诺。所以你需要包装那些async 处理程序(就像你正在做的那样)。

您可以通过在模块顶部给自己一个实用方法来避免每次都这样做:

const appGet = handler => app.get(asyncRoute(handler));

然后用它代替app.get:

appGet('/broken', async (req, res) => {
  throw new Error('Broken!');
});

在某个时候(可能不是现在),您可能想查看Koa。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-01-03
    • 2020-01-25
    • 1970-01-01
    • 1970-01-01
    • 2018-03-04
    • 1970-01-01
    • 2021-10-24
    • 1970-01-01
    相关资源
    最近更新 更多