如何优雅地处理express中的拒绝承诺

如何优雅地处理express中的拒绝承诺,express,promise,es6-promise,express-router,Express,Promise,Es6 Promise,Express Router,我有以下快速控制器 class ThingsController { static async index(req, res, next) { try { const things = await Thing.all(); res.json(things); } catch(err) { next(err); } } } 和路由器 router.route('/things').get(ThingsController.

我有以下快速控制器

class ThingsController {

  static async index(req, res, next) {
    try {
      const things = await Thing.all();
      res.json(things);
    } catch(err) {
      next(err);
    }  
  }
}
和路由器

router.route('/things').get(ThingsController.index)
在我的应用程序中,我计划使用几个控制器来呈现结果

我不想每次都重复try/catch块

我的第一个解决方案是将此逻辑提取到句柄承诺拒绝函数中:

const handlePromiseRejection = (handler) =>

  async (req, res, next) => {
    try{
      await handler(req, res, next);
    } catch(err) {
      next(err);
    };
  };
现在我们可以从ThingsController.index中删除try/catch块,并需要将路由器更改为:

router.route('/things')
  .get(handlePromiseRejection(ThingsController.index))
但是在每一条路线上添加
遥控器可能是一项乏味的任务,我希望有更聪明的解决方案


你有什么想法吗?

所以,如果你真的想处理每一条路线,这就是你处理拒绝承诺的方式

这里还有一个单行ES6版本

代码 尽管如您所问,最简单的方法是在index.js或app.js上使用,在进程上收听
未处理的弹出

process.on("unhandledRejection", (error, promise) => {
  console.log("Unhandled Rejection at:", promise, "reason:", reason);
  // Application specific logging, throwing an error, or other logic here
});

处理路由中的
异步/等待
错误的正常方法是捕获错误并将其传递给
捕获所有
错误处理程序:

app.use(async (req, res) => {
  try {
    const user = await someAction();
  } catch (err) {
    // pass to error handler
    next(err)
  }
});

app.use((err, req, res, next) => {
  // handle error here
  console.error(err);
});
使用
express async errors
包,您可以简单地
抛出
(或者不必担心从某个函数抛出的
错误
)。来自文档:
它没有修补express Router上的所有方法,而是将层#handle属性包装在一个地方,保留express guts的所有其余部分。

用法很简单:

require('express-async-errors'); // just require!
app.use(async (req, res) => {
  const user = await User.findByToken(req.get('authorization')); // could possibly throw error, implicitly does catch and next(err) for you

  // throw some error and let it be implicitly handled !!
  if (!user) throw Error("access denied");
});

app.use((err, req, res, next) => {
  // handle error
  console.error(err);
});

看看这个
express async errors
(可能有人和你有相同的想法)它就像一个charm@naga elixir jar一样工作。请您将此评论转换为答案,我将接受它处理程序(req,res,next)。如果处理程序不是异步函数(如果我们在应用程序中的每个路由处理程序上应用
handlepromiserexing
),则catch(next)
版本的
handlepromiserexing
将不起作用是的,但OP询问了如何使用通用方法处理承诺拒绝。您的解决方案的问题是,当我请求API端点时,我的浏览器将永远挂起,并且由于未处理的承诺拒绝而失败。实际上,它对我有效,无需手动抛出错误。我做了一些测试,检查应用程序在承诺被拒绝时回复了500次,并且通过了测试,而不需要在处理程序中抛出错误。Express有现成的错误处理程序,如果(!user)抛出错误(“访问被拒绝”),则会在出现错误
时以500作为响应
如果您引用这一行,author意味着您可以在路由中抛出错误,而不是执行
next(error)
,包会隐式地为您执行此操作。这只是一个可以抛出错误的示例。
require('express-async-errors'); // just require!
app.use(async (req, res) => {
  const user = await User.findByToken(req.get('authorization')); // could possibly throw error, implicitly does catch and next(err) for you

  // throw some error and let it be implicitly handled !!
  if (!user) throw Error("access denied");
});

app.use((err, req, res, next) => {
  // handle error
  console.error(err);
});