Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call function after completion of async functions inside loop?

I have a forEach loop in NodeJS, iterating over a series of keys, the values of which are then retrieved asynchronously from Redis. Once the loop and retrieval has complete, I want to return that data set as a response.

My problem at the moment is because the data retrieval is asyncrhonous, my array isn't populated when the response is sent.

How can I use promises or callbacks with my forEach loop to make sure the response is sent WITH the data?

exports.awesomeThings = function(req, res) {
    var things = [];
    client.lrange("awesomeThings", 0, -1, function(err, awesomeThings) {
        awesomeThings.forEach(function(awesomeThing) {
            client.hgetall("awesomething:"+awesomeThing, function(err, thing) {
                things.push(thing);
            })
        })
        console.log(things);
        return res.send(JSON.stringify(things));
    })
like image 777
Anonymous Avatar asked Nov 28 '25 16:11

Anonymous


1 Answers

I use Bluebird promises here. Note how the intent of the code is rather clear and there is no nesting.

First, let's promisify the hgetall call and the client -

var client = Promise.promisifyAll(client);

Now, let's write the code with promises, .then instead of a node callback and aggregation with .map. What .then does is signal an async operation is complete. .map takes an array of things and maps them all to an async operation just like your hgetall call.

Note how Bluebird adds (by default) an Async suffix to promisifed methods.

exports.awesomeThings = function(req, res) {
    // make initial request, map the array - each element to a result
    return client.lrangeAsync("awesomeThings", 0, -1).map(function(awesomeThing) {
       return client.hgetallAsync("awesomething:" + awesomeThing);
    }).then(function(things){ // all results ready 
         console.log(things); // log them
         res.send(JSON.stringify(things)); // send them
         return things; // so you can use from outside
    });
};
like image 125
Benjamin Gruenbaum Avatar answered Dec 01 '25 06:12

Benjamin Gruenbaum



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!