【问题标题】:Simplify query checks in Node.js+mongoose简化 Node.js+mongoose 中的查询检查
【发布时间】:2015-04-12 13:48:26
【问题描述】:

我正在使用 Node.js、restify 和 mongoose 编写一个非常简单的 RESTful API,但代码变得复杂且冗长。这是由我每次进行查询时必须做的所有检查引起的。例如,下面的代码显示了端点 POST /users/:user1/follow/:user2 的控制器。

exports.followUser = function(req, res, next) {
  User.findOne({ username: req.params.user1 }, function(err, user1) {
    if (err) {
      res.status(500);
      res.json({ type: false, data: 'Error occurred: ' + err });
    } else {
      if (user1) {
        User.findOne({ username: req.params.user2 }, function(err, user2) {
          if (err) {
            res.status(500);
            res.json({ type: false, data: 'Error occurred: ' + err });
          } else {
            if (user2) {
              user2.followers.push(user1);
              user2.save();
              res.json({
                type: true,
                data: 'User ' + req.params.user1 + ' is now following user ' + req.params.user2
              });
            } else {
              res.json({
                type: false,
                data: 'User ' + req.params.user2 + ' not found'
              });
            }
          }
        });
      } else {
        res.json({
          type: false,
          data: 'User ' + req.params.user1 + ' not found'
        });
      }
    }
  });
};

如何简化此代码?如您所见,我正在检查每个 findOne 的结果以了解收到的用户是否存在,并且我还为每个错误返回 json 答案,但这很乏味。有没有办法自动化这个?

【问题讨论】:

    标签: node.js mongoose refactoring restify


    【解决方案1】:

    你可以使用 Mongoose 的 promise 来清理它。比如:

    exports.followUser = function(req, res, next) {
      User.findOne({
        username: req.params.user1
      }).exec().then(function(user1) {
        if (user1 === null) {
          throw new Error('User ' + req.params.user1 + 'not found');
        }
    
        return User.findOneAndUpdate({
          username: req.params.user2
        }, {$push: {followers: user1}}).exec();
      }).then(function(user2) {
        if (user2 === null) {
          throw new Error('User ' + req.params.user2 + ' not found');
        }
    
        res.json({
          type: true,
          data: 'User ' + req.params.user1 + ' is now following user ' + req.params.user2
        });
      }, function(err) {
        res.status(500);
        res.json({ type: false, data: 'Error occurred: ' + err });
      });
    };
    

    【讨论】:

    • 看起来很有希望。我会试试看。谢谢。
    • 在将 user1 保存到 res.locals 时出现此错误:'发生错误:TypeError:无法设置未定义的属性'user1'。有什么想法吗?
    • 抱歉,res.locals 是 Express 特定对象。只需使用findOneAndUpdate 即可删除 ned。更新以反映这一点。
    【解决方案2】:

    Promises 有助于使代码更具可读性,我看到了另外两种简化代码的方法。通过使用内置的 restify 错误类型处理错误,您将减少几行代码并可能获得一些易读性

    其次,您可以只更新 user2 而不是获取他/她并简化您的 if 语句。此外,您还获得了一个额外的错误检查,您现在在保存时缺少该检查。我想出了这样的事情:

    exports.followUser = function(req, res, next) {
        User.findOne({username: req.params.user1}, function (err, user1) {
    
            next.ifError(err);
    
            if (!user1) 
                return next(new restify.NotFoundError('User ' + req.params.user1 + ' not found'));
    
    
            User.update({username: req.params.user2}, {$push: {followers: user1}}, function (err, updated) {
    
                next.ifError(err);
    
                if(!updated)
                    return next(new restify.NotFoundError('User ' + req.params.user2 + ' not found'));
    
                return res.send({
                    type: true,
                    data: 'User ' + req.params.user1 + ' is now following user ' + req.params.user2
                });
                next();
    
            });
    
        });
    };
    

    如果您想保留在未找到用户时返回带有额外信息的 200 响应的约定,您可以创建自定义错误类:

    var restify = require('restify');
    var util = require('util');
    
    function MyError(message) {
      restify.RestError.call(this, {
        restCode: 'MyError',
        statusCode: 200,
        message: message,
        constructorOpt: MyError
      });
      this.name = 'MyError';
    };
    util.inherits(MyError, restify.RestError);
    

    然后根据文档为该错误创建一个全局处理程序,以便您可以按照您想要的方式返回 json。

    【讨论】:

    • 我喜欢更新的部分,而不是获取和保存。好点子。但我不明白错误处理。当你调用 next(err) 时发生了什么?那个错误句柄在哪里?
    • 查看我发给 upi 的文档链接。您创建一个带有额外错误参数的处理程序,并在所有 api 路由之后注册它。如果可以集中处理某些类型的错误。我会更新的。
    • 您正在链接到 Express 文档。这与restify兼容吗?我根本没有使用 Express。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-24
    • 1970-01-01
    • 1970-01-01
    • 2011-04-20
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多