如何等待mongoose .exec功能完成?

时间:2015-10-21 21:15:40

标签: javascript node.js mongoose

我是由asychronous nodejs和mongoose共同完成的。简单地说,我想发布一个用户名数组并检查,如果用户名在数据库中,那么我将它放在valid数组中,否则,将它放在invalid数组中。

这是我目前的代码:

var User = require('../../db/models/user');

api.post('/userlist', function(req, res) {

  var invalid = []; // usernames which can not be found in database
  var valid = []; // usernames which can be found in database

  (req.body.userlist).forEach(function(username) {

    User
      .findOne({username: username})
      .exec(function(err, user) {

        if (err) {
          res.send(err);
          return;

        } else if (!user) {

          invalid.push(username);

        } else {

          valid.push(req.params.item);
        }
      });
  });

  res.send({
    Invalid: invalid,
    Valid: valid
  });

});

当我执行上面的代码时,它直接输出初始空数组。

Invalid: [],
Valid: []

我知道这是因为nodejs首先执行此res.send然后执行函数.exec(function(err, user),但我不知道如何获得正确的invalidvalid数组,请参阅指教。

3 个答案:

答案 0 :(得分:5)

您最好的选择是使用承诺:

api.post('/userlist', (req, res) => {
    // Takes a username and returns a promise for information on that username.
    function findByUsername(username) {
        return new Promise((resolve, reject) =>
            User.findOne({username}).exec((err, user) => 
                err ? reject(err) : resolve(user)
            )
        );
    }

    // Iterate the array and transform each user to a promise for data on that user. 
    Promise.all(req.body.userlist.map(findByUsername))
        // Then, when all of the promises in that new array resolve
        .then(allUserDataInOrder => {
            // Find all the valid ones (if (user))
            let Valid = allUserDataInOrder.filter(Boolean); // Only those who are truthy
            // And all the invalid ones (if (!user))
            let Invalid = allUserDataInOrder.filter(userData => !userData); // Sadly, no convenient function here :(
            // And send both away
            res.send({Valid, Invalid}); // Short syntax FTW!
        })
        .catch(res.send); // Called with error object if any.
});

答案 1 :(得分:2)

虽然这些其他解决方案解决了您要完成的任务,但他们仍然通过迭代 private void button3_MouseHover(object sender, EventArgs e) { UltraToolTipInfo info = new UltraToolTipInfo(); info.ToolTipTextStyle = ToolTipTextStyle.Formatted; String tooltipText = "x < y <br/><br/> <span style=\"font-weight:bold;\">This is bold.</span> And this is not bold."; tooltipText = tooltipText.Replace("<", "&lt;"); tooltipText = tooltipText.Replace(">", "&gt;"); info.ToolTipTextFormatted = tooltipText; ultraToolTipManager1.SetUltraToolTip((Control)sender, info); } 来加入糟糕的设计。对列表中的每个项目执行1个查询是非常低效的。使用findOne()查询和基本地图,您可以使用单个查询:

$in

答案 2 :(得分:1)

尝试使用异步模块:

var invalid = [];
var valid = [];

async.each(req.body.userlist, function(name, next) {
  User.findOne({username: name}, function(err, user) {
    if (err) {
     return next(err);
    }
    if (!user) {
      invalid.push(name);
    } else {
      valid.push(name);
    }

    next();
  )};
}, function(err) {
   if (err) {
     return res.send(err);
   }

   res.send({
     Invalid: invalid,
     Valid: valid
   });
});