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

IT技术 javascript node.js mongodb promise q
2021-01-15 03:40:16

我在循环中进行多个 mongoDB 查询。并希望将所有结果作为一个数据数组发送。但是当我简单地使用返回来发送数据时,它只是返回未定义的并且不等待所有数据库请求的结果。我也尝试使用 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个回答

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

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

在您的情况下,这些是哪些功能?它是getPrayerInCatforEach回调和Prayer.find

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

为每个没有的函数创建一个直接包装器

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

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

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

对异步结果执行某些操作的所有操作都会进入.then回调

...并返回结果。地狱,如果“某物”是异步的,那么结果甚至可以是一个Promise!有了这个,我们就可以写出完整的回调函数了:

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,它们的异步任务并行运行并以未知顺序解析。我们想要等待所有这些 - 即当每个任务完成时得到一个解决所有结果的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。

getPrayerCat('').then(function(data){ getPrayerInCat(data) }).then(function(data2){ console.log(data2) }) var getPrayerInCat = function(data){ var result ; var finalData = []; if(data.length >0){ var promises = data.map(getPrayerCount); 返回 Q.all(promises); } }
2021-03-19 03:40:16
函数 getPrayerCount(data2) { var id = data2.id; return find({prayerCat:id}) .then(function(prayer) { if (!prayer) data2.prayersCount = 0; else data2.prayersCount = prompt.length; return data2; }); }
2021-03-21 03:40:16
您在then回调中忘记了规则 1 它需要是没有返回任何东西,Promise解析为……getPrayerCat('').then(function(data){ return getPrayerInCat(data); }).then(…)undefined
2021-03-30 03:40:16
这次我又遇到了同样的问题@Bergi 添加了一个循环
2021-04-05 03:40:16
我已经使用了你的代码,但同样的问题它返回表单 find 并且不等待来自 db 的 resukt 。所以最终的结果是不确定的。
2021-04-08 03:40:16