在内部forEach循环中集成asynchronousmongo调用

我有两个循环,用户的外部循环和内部的循环遍历每个用户的场所ID。 在内部循环中,我想查找场地并将其附加到外观( userItem )中定义的数组。 但是,因为forEach是同步的,并且mongo数据库查找是asynchronous的,所以结果始终为空。 我试图整合这个答案,但无济于事。 这个怎么做?

 ret = []; users.forEach(function(user) { var userItem = user.getSanitised('ADM'); userItem.venues = []; var tmp = []; userItem.adminVenueIds.forEach(function(adminVenueId){ tmp.push(function(callback) { Venue.findOne({_id:adminVenueId}, function(error, venue) { callback(null, venue.toObject()); }); }); }); async.parallel(userItem.venues, function(err, result) { /* this code will run after all calls finished the job or when any of the calls passes an error */ if (err) return console.log(err); userItem.venues.push(result); }); ret.push(userItem); }); 

尝试以下,但也不起作用

 users.forEach(function(user) { var userItem = []; async.series({ setUserItem : function(callback) { userItem = user.getSanitised('ADM'); callback(null, 'OK'); }, setUserVenues : function(callback) { userItem.venues = []; user.adminVenueIds.forEach(function(adminVenueId,index) { Venue.findOne({_id:adminVenueId}, function(error, venue) { userItem.venues.push(venue.toObject()); if((index+1) == user.adminVenueIds.length) callback(null, 'OK'); }); }); } }, function(error, results) { if(error) winston.error(error); ret.push(userItem); } ); }); 

我想你可能想看看使用mongoose。 它是一个在MongoDB之上的NodeJS应用程序层,提供了更像SQL的体验。

http://mongoosejs.com

你可以简单地把一个if语句(在你的情况下把条件作为数组的长度),然后当循环完成,你可以通过调用一个函数继续执行它的事情(或者把你的代码放在那里,但是它会开始看起来凌乱)

 var ret = []; var test = []; for (var i = 0; i < 20; i++) { for (var x = 0; x < 20; x++) { setTimeout(function() { test.push("Test"+x); if (x === 20) { finishIt(); } }, 300) } } function finishIt() { console.log(test); ret.push(test); } 

我结束了以下解决scheme。 这很脏,但我想这只是nodejs是nodejs。

 users.forEach(function(user) { var userItem = user.getSanitised('ADM'); userItem.venues = []; user.adminVenueIds.forEach(function(adminVenueId) { Venue.findOne({_id:adminVenueId}, function(error, venue) { userItem.venues.push(venue.toObject()); }); }); (function(){ if(userItem.venues.length == user.adminVenueIds.length) { ret.push(userItem); } else { setTimeout(arguments.callee, 30); } })(); });