Q.all在forEach之前运行

时间:2016-05-17 14:15:55

标签: node.js asynchronous q

我正在尝试创建一个读取电子邮件数组的promise函数,然后找到用户ID并将其推送到另一个数组。

问题是我的Q.all函数在_.forEach完成之前正在运行。看看:

var deferred = Q.defer(),
    promises = [],
    _ = require('lodash');

_.forEach(users, function(user) {
    User.findOne({
      username: user
    }, function(err, member) {
      if (err)
        console.log(err);

      var memberId = member._id;
      promises.push(members.push(memberId));
    });
});

Q.all(promises)
  .then(function(promises) {
    deferred.resolve(promises);
    console.log(promises); // This always returns -> []
  })
  .catch(function(err) {
    deferred.reject(err);
  });

return deferred.promise;

所以每当我尝试console.log我的承诺数组时,我得到一个空数组。我甚至尝试使用JavaScript本机forEach函数,但它没有用。

问题是forEach还是Q.all不是这种情况的适当函数?

提前致谢。

已解决 Robert Moskal建议的解决方案

就我而言,async库和Q.defer()解决了这个问题。

var async = require('async'),
    deferred = Q.defer();

async.map(users, function(each, done){
  User.findOne({
    username: each
  }, function(err, member) {
      if (err)
        console.log(err);
        done(null, member._id);
      });
  }, function(err, results){
    if (err)
      deferred.reject(err);
    deferred.resolve(results);
});

return deferred.promise;

1 个答案:

答案 0 :(得分:1)

你的问题是User.findOne函数是异步的,所以在promise数组上推送任何东西之前执行Q.all函数。

通常最好不要混合回调和承诺。至于修理它。如果那是一个猫鼬模型,那么你可以使用基于promise的findOne版本:

var deferred = Q.defer(),
    promises = [],
    _ = require('lodash');

_.forEach(users, function(user) {
    promises.push(User.findOne({
      username: user}));
});

Q.all(promises)
  .then(function(promises) {
    deferred.resolve(promises);
    console.log(promises); // This always returns -> []
  })
  .catch(function(err) {
    deferred.reject(err);
  });

return deferred.promise;

或者您可以使用异步库,它可能看起来像这样:

async.map(users, function(each, done){

 User.findOne({
      username: user
    }, function(err, member) {
      if (err)
        console.log(err);
        done(null, member._id); 

    });
},
function(err, results){
  //results holds your array of ids
    }
);