我在循环中进行了多个mongoDB查询。并希望将所有结果作为一个数据数组发送。但是当我简单地使用return来发送数据时,它只是返回undefined而不等待所有DB请求的结果。我也尝试使用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返回未定义。
让我们从使用诺言的一般规则开始:
每个执行异步操作的函数都必须返回一个promise
您要使用哪些功能?是getPrayerInCat,forEach回调和Prayer.find。
getPrayerInCat
forEach
Prayer.find
嗯,Prayer.find不返回promise,它是一个库函数,因此我们无法对其进行修改。规则2起作用:
为每个不创建的函数创建一个立即包装
在我们的情况下,使用[Q的节点接口助手]很容易:
var find = Q.nbind(Prayer.find, Prayer);
现在,我们只有承诺,而不再需要任何延期。第三条规则起作用:
所有与异步结果有关的事情都会进入.then回调
.then
…并返回结果。地狱,如果“某物”是异步的,那么结果甚至是一个承诺!这样,我们可以编写完整的回调函数:
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()将为我们带来多个承诺,其异步任务并行运行并以未知顺序解析。我们希望等待所有这些,例如,当每个任务完成时,获得可以解决所有结果的承诺。
getPrayerCount()
对于此类复杂的任务,请勿尝试提出自己的解决方案:
检查您库的API
在那里,我们发现Q.all,它正是这样做的。getPrayerInCat现在写作变得轻而易举:
Q.all
function getPrayerInCat(data) { var promises = data.map(getPrayerCount); // don't use forEach, we get something back return Q.all(promises); // ^^^^^^ Rule 1 }
如果我们需要对Q.all解析数组进行任何操作,只需应用规则3。