Express.js:传递引发的异步错误

时间:2018-07-04 11:06:55

标签: javascript node.js express

我注意到我的Express应用程序中有一个重复出现的模式,我认为可以对其进行优化。基本上,我有一条路由调用带有一些异步函数的方法。

index.js

const controller = require('./controller.js');

const router = new Router();

router.post('/user', controller.createUser);

module.exports = router;

controller.js

exports.createUser = async (req, res, next) => {
    try {
        // asynchronous calls, etc.
    } catch (e) {
        // pass error to middleware
        next(e);
    }
}

我的每个控制器方法中都重复出现try/catch块。我希望将捕获的错误传递给我的错误处理中间件。因此,在我的每个控制器功能中传递错误似乎不现实且重复。我可以重构吗?

如果将控制器方法包装在这样的函数中怎么办?

index.js

const controller = require('./controller.js');

const router = new Router();

const handleErrors = (func) => async (req, res, next) => {
  try { await func(req, res, next) }
  catch (e) { return next(e) }
};

router.post('/user', handleErrors(controller.createUser));

module.exports = router;

controller.js

exports.createUser = async (req, res, next) => {
    // asynchronous calls, etc.
    if (a !== b) {
        // errors can be passed to middleware as such
        throw new CustomError(400, 'a is not equal to b');
    }
}

这是一个合适的解决方案吗? Express是否具有完成同一件事的内置方法?我应该对以这种方式重构整个应用程序保持谨慎吗?

2 个答案:

答案 0 :(得分:2)

  

这是一个合适的解决方案吗?

是的,看起来不错。

  

Express是否具有完成同一件事的内置方法?

不,Express是在引入async / await之前编写的。

  

我应该以这种方式重构整个应用程序吗?

我不这么认为。我怎么写:

const handleErrors = (func) => (req, res, next) => func(req, res).then(() => next(), next);

答案 1 :(得分:1)

我建议您这篇文章:https://medium.com/@Abazhenov/using-async-await-in-express-with-node-8-b8af872c0016

如本文所述,这应该是中间件:

const asyncMiddleware = fn =>
  (req, res, next) => {
    Promise.resolve(fn(req, res, next))
      .catch(next);
  };

这是控制器的外观:

router.get('/users/:id', asyncMiddleware(async (req, res, next) => {
    /* 
      if there is an error thrown in getUserFromDb, asyncMiddleware
      will pass it to next() and express will handle the error;
    */
    const user = await getUserFromDb({ id: req.params.id })
    res.json(user);
}));

router.post('/users', asyncMiddleware(async (req, res, next) => {
  const user = await makeNewUser(req.body);
  res.json(user)
}))