简化Node.js + mongoose中的查询检查

时间:2015-04-12 13:48:27

标签: node.js mongoose refactoring restify

我正在编写一个非常简单的RESTful API,使用Node.js,restify和mongoose,但代码变得越来越复杂。这是由我每次进行查询时必须执行的所有检查引起的。例如,下一个代码显示端点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答案,但这很乏味。有没有办法自动化这个?

2 个答案:

答案 0 :(得分:1)

你可以使用Mongoose的承诺来清理它。类似的东西:

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 });
  });
};

答案 1 :(得分:1)

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格式。