Q.all在forEach之前运行

我试图做一个承诺函数,读取电子邮件数组,然后find用户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本地forEachfunction,但它没有工作。

是否每个问题或Q.all是这种情况下适当的function?

提前致谢。


解决 (解决scheme由罗伯特莫斯卡尔build议)

就我而言, 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; 

你的问题是User.findOne函数是asynchronous的,所以Q.all函数在promise数组上被压入之前就被执行了。

通常最好不要混用callback和承诺。 至于修理它。 如果这是一个mongoose模型,那么你可以使用基于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; 

或者你可以使用可能看起来像这样的asynchronous库:

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