NodeJS 中间件在返回后继续执行



>我有以下中间件:

const mongoose = require('mongoose');
module.exports = function(req, res, next) {
  const keys = Object.keys(req.params);
  keys.forEach(elem => {
    if (
      (elem.includes('id') || elem.includes('Id')) &&
      !mongoose.Types.ObjectId.isValid(req.params[elem])
    )
      return res
        .status(400)
        .json({ msg: `id: ${req.params[elem]} is invalid` });
  });
  next();
};

它在 GET 请求中调用:

// @route   GET api/movies/:id
// @desc    Get a movie with specified id from db
// @access  Public
router.get('/:id', checkId, async (req, res) => {
const movie = await Movie.findById(req.params.id);
res.json(movie);
});

当我在邮递员中使用无效 id 发出请求(例如:1234(时,我收到正确的响应是 400,消息为:"id 1234 无效",但执行仍然传递给 reqest 回调代码,并且当我尝试使用无效 id 访问数据库时会抛出错误。

所以问题是为什么中间件仍然允许执行 next(( 即使它已经与 400 一起返回?

您需要通过调用 next("some-error") 来告诉路由器有问题。 例如,您可以执行以下操作:

module.exports = function(req, res, next) {
  const keys = Object.keys(req.params);
  keys.forEach(elem => {
    if (
      (elem.includes('id') || elem.includes('Id')) &&
      !mongoose.Types.ObjectId.isValid(req.params[elem])
    ) {
      res
        .status(400)
        .json({ msg: `id: ${req.params[elem]} is invalid` });
      return next("invalidinput");
    }
  });
  next();
};

或者,如果您愿意,可以通过在路由器外部设置结果来更通用,如下所示:

在中间件中:

module.exports = function(req, res, next) {
  const keys = Object.keys(req.params);
  keys.forEach(elem => {
    if (
      (elem.includes('id') || elem.includes('Id')) &&
      !mongoose.Types.ObjectId.isValid(req.params[elem])
    ) {
      // === Report the error and let the router handle it
      return next({
        type: "invalidinput",
        msg: `id: ${req.params[elem]} is invalid`
      );  
    }
  });
  next();
};

然后在路由器底部:

// handle any errors
router.use(err, req, res, next) => {
  if (err) {
    if (err.type === "invalidinput") {
      return req.status(400).json({msg: err.msg});
    }
    else {
      return res.status(500).json({msg: "Internal error."});
    }
  }
  return next();
}

这里另一个可能的解决方案是将 forEach 转换为经典的 for 循环,归仁 使这个中间件同步运行

module.exports = function(req, res, next) {
  const keys = Object.keys(req.params);
  for (let i = 0; i < keys.length; i++) {
    if (
      (keys[i].includes('id') || keys[i].includes('Id')) &&
      !mongoose.Types.ObjectId.isValid(req.params[keys[i]])
    )
      return res
        .status(400)
        .json({ msg: `id: ${req.params[keys[i]]} is invalid` });
  }
  next();
};

最新更新