andunslg
andunslg

Reputation: 791

Wait until all the function calls inside for-loop ends its execution - Javascript

I have a function which contains another function call inside a for loop.

outerFunction(){ 
    for (var j = 0; j < geoAddress.length; j++) {
         innerFunction(j);
    }
}

I need to wait till all the calls to innerFunction is complete. If I need parallel execution of these functions, how to achieve this in JavaScript?

Upvotes: 1

Views: 4264

Answers (4)

Mauno V&#228;h&#228;
Mauno V&#228;h&#228;

Reputation: 9788

If you don't want to use external library for this you could make a scope object such as process which keeps track of how many innerFunction calls are still pending, and calls outer callback cb when it is finished.

The point with this is that you still get the benefits of async execution, but you just make sure that your code won't execute the next part until all innerFunction belonging to outerFunction are actually finished:

outerFunction(function() {
    console.log("All done for outerFunction! - What you should do next?");

    // This block is executed when all innerFunction calls are finished.

});

JavaScript:

// Example addresses
var geoAddress = ["Some address X", "Some address Y"];

var innerFunction = function(geoAddress, process) { 

    // Your work to be done is here...
    // Now we use only setTimeout to demonstrate async method
    setTimeout(function() {

        console.log("innerFunction processing address: " + geoAddress);

        // Ok, we update the process
        process.done();   

    }, 500);

};

var outerFunction = function(cb) { 

    // Process object for tracking state of innerFunction executions
    var process = { 

        // Total number of work ahead (number of innerFunction calls required).
        count: geoAddress.length,

        // Method which is triggered when some call of innerFunction finishes  
        done: function() {

            // Decrease work pool
            this.count--;

            // Check if we are done & trigger a callback
            if(this.count === 0) { 
                setTimeout(cb, 0);
            }            
        }
    };

    for (var j = 0; j < geoAddress.length; j++) {
        innerFunction(geoAddress[j], process);
    }

};

// Testing our program
outerFunction(function() {
    console.log("All done for outerFunction! - What you should do next?");

    // This block is executed when all innerFunction calls are finished.

});

Output:

innerFunction processing address: Some address X
innerFunction processing address: Some address Y
All done for outerFunction! - What you should do next? 

Here is js fiddle example

Cheers.

Upvotes: 0

m.casey
m.casey

Reputation: 2599

Edit - Doing Things the Node Way Using Q Promise Library

If you're using the Q promise library, then try the following:

outerFunction(){
    var promises = [];

    for (var j = 0; j < geoAddress.length; j++) {
        deferreds.push(innerFunction(j));
    }

    Q.all(promises).then(function(){ 
        // do things after your inner functions run 
    });
}

Even if you're not using this particular library, the principle is the same. One should have one's function return a promise or have it wrapped in a promise as in the Q.denodify method, push all calls to an array of promises, pass said array to your library's equivalent of .when() (jQuery) or .all() (Q Promise Library) and then use .then() to do things after all promises are resolved.

Upvotes: 2

Sergey Yarotskiy
Sergey Yarotskiy

Reputation: 507

outerFunction() { 
    var done = 0;

    function oneThreadDone() {
        done++;
        if (done === geoAddress.length) {
            // do something when all done
        }
    }

    for (var j = 0; j < geoAddress.length; j++) {
         setTimeout(function() { innerFunction(j, oneThreadDone); }, 0);
    }
}

and inside inner_function call oneThreadDone() function (reference passed throught param)

Upvotes: 0

lbrazier
lbrazier

Reputation: 2654

Check out the async library. https://www.npmjs.org/package/async

Check out the documentation on "whilst". It sounds like it does just what you need. whilst(test, fn, callback)

var count = 0;

async.whilst(
function () { return count < 5; },
function (callback) {
    count++;
    setTimeout(callback, 1000);
},
function (err) {
    // 5 seconds have passed
}

);

Upvotes: 2

Related Questions