在返回从循环中调用的数据库查询检索到的数据中的问题

我在循环中做了多个mongoDB查询。 并希望将所有结果作为一个数据数组发送。但是,当我简单地使用返回来发送数据时,它只是简单地返回undefined,不要等待所有数据库请求的结果。 我也尝试使用q.moulde,但同样的问题。

码:

var getPrayerInCat = function(data){ var result ; var finalData = []; if(data.length >0){ data.forEach(function(data2){ var id= data2.id; Prayer.find({prayerCat:id},function(err,prayer){ var deferred = Q.defer() if (err) { // ... console.log('An error has occurred'); // res.send(err); result= finalData = err } else { if(!prayer){ // console.log(data2.id+'--0'); data2.prayersCount = 0; result = deferred.resolve(finalData.push(data2)) } else { // console.log(data2.id+'--'+prayer.length); data2.prayersCount = prayer.length; // console.log(prayer) result = deferred.resolve(finalData.push(data2)) } // else for data forward } deferred.promise; }) // deferred.resolve(finalData); }) /*if(finalData.length > 0) { return finalData;}*/ } } 

finalData返回undefined。

让我们从使用promise的一般规则开始:

每个执行asynchronous事件的函数都必须返回一个promise

你的情况下这些function是什么? 它是getPrayerInCatforEachcallback和Prayer.find

嗯, Prayer.find不会返回一个承诺,它是一个库函数,所以我们不能修改它。 规则2发挥作用:

为每个不包含的函数创build一个立即包装

在我们的例子中,使用Q的节点接口帮助器很容易:

 var find = Q.nbind(Prayer.find, Prayer); 

现在我们只有承诺,不再需要任何延期。 第三条规则发挥作用:

所有与asynchronous结果有关的东西都会进入一个.thencallback

…并返回结果。 地狱,这个结果甚至可以是一个承诺,如果“某些东西”是asynchronous的! 有了这个,我们可以编写完整的callback函数:

 function getPrayerCount(data2) { var id = data2.id; return find({prayerCat:id}) // ^^^^^^ Rule 1 .then(function(prayer) { // ^^^^^ Rule 3 if (!prayer) data2.prayersCount = 0; else data2.prayersCount = prayer.length; return data2; // ^^^^^^ Rule 3b }); } 

现在,我们有一些更复杂的事情:一个循环。 反复调用getPrayerCount()会得到多个promise,它们的asynchronous任务并行运行,并以未知的顺序parsing。 我们希望等待所有的结果 – 即得到一个承诺,当每个任务完成时,所有的结果都会得到解决。

对于这样复杂的任务,不要试图拿出你自己的解决scheme:

检查你的图书馆的API

在那里,我们发现Q.all ,正是这个。 编写getPrayerInCat现在是一件轻而易举的事情:

 function getPrayerInCat(data) { var promises = data.map(getPrayerCount); // don't use forEach, we get something back return Q.all(promises); // ^^^^^^ Rule 1 } 

如果我们需要对Q.all解决的数组做任何事情, Q.all应用规则3。