Muddassir Khanani Muddassir Khanani - 8 months ago 17
Javascript Question

Issue in returning data retrieved from DB queries called in the loop

I making multiple mongoDB queries in loop. and want to send the all results as one data array.But when I simple use the return for send the data it simply return undefined and do not wait for results of all DB request. I also tried to use q.moulde but same issue.


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

/*if(finalData.length > 0) { return finalData;}*/

finalData is returned undefined.


Let's start with the general rule for using promises:

Every function that does something asynchronous must return a promise

Which functions are these in your case? It's getPrayerInCat, the forEach callback, and Prayer.find.

Hm, Prayer.find doesn't return a promise, and it's a library function so we cannot modify it. Rule 2 comes into play:

Create an immediate wrapper for every function that doesn't

In our case that's easy with Q's node-interfacing helpers:

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

Now we have only promises around, and do no more need any deferreds. Third rule comes into play:

Everything that does something with an async result goes into a .then callback

…and returns the result. Hell, that result can even be a promise if "something" was asynchronous! With this, we can write the complete callback function:

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

Now, we have something a bit more complicated: a loop. Repeatedly calling getPrayerCount() will get us multiple promises, whose asynchronous tasks run in parallel and resolve in unknown order. We want to wait for all of them - i.e. get a promise that resolves with all results when each of the tasks has finished.

For such complicated tasks, don't try to come up with your own solution:

Check the API of your library

And there we find Q.all, which does exactly this. Writing getPrayerInCat is a breeze now:

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

If we needed to do anything with the array that Q.all resolves to, just apply Rule 3.