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

时间:2014-09-09 18:53:19

标签: javascript node.js mongodb promise q

我在循环中进行多个mongoDB查询。并且想要将所有结果作为一个数据数组发送。但是当我简单地使用return来发送数据时,它只返回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以未定义的方式返回。

1 个答案:

答案 0 :(得分:17)

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

  

每个执行异步操作的函数都必须返回一个承诺

您的案例中有哪些功能?它是getPrayerInCatforEach回调和Prayer.find

嗯,Prayer.find没有返回承诺,而且它是一个库函数,因此我们无法对其进行修改。规则2发挥作用:

  

Create an immediate wrapper代表的所有功能

在我们的情况下Q's node-interfacing helpers很容易:

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

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

  

使用异步结果执行操作的所有内容都会转入.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()将获得多个promise,其异步任务并行运行并以未知顺序解析。我们希望等待所有这些 - 即获得一个在每个任务完成时解析所有结果的承诺。

对于这些复杂的任务,请不要尝试提出自己的解决方案:

  

检查您图书馆的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解析的数组执行任何操作,只需应用规则3.