Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Q.all work in NodeJS?

I have the following code:

var a = [1,2,3,4,5];
var promises = [];
a.forEach(function(item,index){
    var deferred = Q.defer();
    doSomething().then(function(){
        deferred.resolve(true);
        promises.push(deferred);
    });
});

Q.all(promises).then(function(data){
    console.log("something!!");
});

How does Q.all know that promises array has all the promises required by forEach loop? Sometimes, my Q.all runs before forEach. Please tell me where I am going wrong.

doSomething() is an asynchronous function which returns a promise.

like image 848
skjindal93 Avatar asked Mar 01 '26 14:03

skjindal93


1 Answers

Q.all cannot run before your forEach, since forEach is synchronous.

But you actually push things in the array after Q.all has been called. Your way of using promises is a bit awkward : no need to use a deffered in a promise!

Plus, you don't want to push the deffered itself but the promise that it holds, after rejecting or resolving it. See below for more info on how to "promisify" an asynchronous funtion.

Deffered are used to define promises out of symple callback-based asynchronous code. Since doSomething() returns a promise (you are using .then()), you could actually just do :

var a = [1,2,3,4,5];
var promises = [];
a.forEach(function(item,index){
    var promise = doSomething().then(function(data){
        return Q(true);
    });
    promises.push(promise);
});

Q.all(promises).then(function(data){
    console.log("something!!");
});

Then promises will be directly populated with promises, without any delay.

EDIT : since you are asking about doSomething not being promise-enabled, here is what you could do:

Let's say doSomething takes as a parameter a callback to execute after some asynchronous task.

Then you could wrap doSomething that way:

function doSomethingPromise(){
    var defered = Q.defer();
    doSomething(function(err,data){
       if(err){
           defered.reject(err);
       }
       else{
           defered.resolve(data);
       }
    });
    return defered.promise;
}

and then use doSomethingPromise() as mentionned above, instead of doSomething, since this one returns a promise.

like image 70
Tiesselune Avatar answered Mar 04 '26 02:03

Tiesselune



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!