快速控制器用于捕获错误处理

时间:2018-03-10 14:34:50

标签: node.js express

如何在express的控制器中实现DRY?我发现我重复了捕获函数的代码。

exports.getUsers = (req, res) => {

  Ad.find({})
  .then(data=>{
    res.json({status:1, data})
  })
  .catch(err => {
      res.status(400).send({
          msg: err
      })
  })
}

exports.getUser = (req, res) => {

  User.findOneById({id: res.body.id})
  .then(data=>{
    res.json({status:1, data})
  })
  .catch(err => {
      res.status(400).send({
          msg: err
      })
  })
}

大多数时候我们只想返回相同的错误对象,但是在一个控制器文件中,我们有很多这样的

.catch(err => {
          res.status(400).send({
              msg: err
          })
      })

我们可以在任何地方实现一次作为中间件吗?

2 个答案:

答案 0 :(得分:1)

您可以使用捕获错误的中间件来包装每条路线。

const errorHandler = fn => (req, res, next) => {
  Promise.resolve(fn(req, res, next))
    .catch(err => {
      res.status(400).send({ msg: err.message });
    });
};

app.post('/users', errorHandler(getUsers));

但是使用这种方法,每个错误都将以状态400发送,您也可能会暴露关键信息。我建议使用自定义错误将Error子类化,例如BadRequestError并在控制器中抛出此错误并更改中间件,如下所示:

const errorHandler = fn => (req, res, next) => {
  Promise.resolve(fn(req, res, next))
    .catch(err => {
      if (err.name === 'BadRequestError') {
        res.status(400).send({ msg: err.message });
      } else {
        // log the error
        res.status(500).send({ msg: 'Internal Server Error' })
      }
    });
};

一个很好的副作用:通过使用errorHandler包装每个端点,您的应用程序变得非常健壮,因为如果您的代码失败,您将始终发送响应并且永远不会在客户端获得超时。

答案 1 :(得分:0)

不是中间件,但您可以创建一个以sendErrorResponseres为参数的函数err,例如:

function sendErrorResponse(res, err) {
    return res.status(400).send({
              msg: err
    })
}

然后将其用作:

User.findOneById({id: res.body.id}).then(data=>{
    res.json({status:1, data})
})
.catch(err => sendErrorResponse(res, err))

如果需要,可以将sendErrorResponse移到单独的文件中,并在多个控制器中使用它。