Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to know when async for loop is done?

I have a for loop that kicks off hundreds of async functions. Once all functions are done I need to run one last function but I can't seem to wrap my head around it knowing when all functions are complete.

I've tried promises but as soon as any of the functions in the loop resolve then my promise function completes.

for(var i = 0; i < someArray.length; i ++){
// these can take up to two seconds and have hundreds in the array
asyncFunction(someArray[i];
} 

How can I tell once every function has completed?

like image 929
Skej Avatar asked Feb 10 '23 10:02

Skej


2 Answers

An increment

You can add a callback which increments:

for (var i = 0; i < len; i++) {
    asycFunction(someArray[i]);
    asycFunction.done = function () {
        if (i == someArray.length - 1) {
            // Done with all stuff
        }
    };
}

A recursive approach

This type of approach is more liked by some developers but (might) take longer to execute because it waits for one to finish, to run another.

var limit = someArray.length, i = 0;

function do(i) {
    asyncFunction(someArray[i]);
    asyncFunction.done = function () [
        if (i++ == someArray[i]) {
            // All done!
        } else { do(i); }
    }
}
do(i++);

Promises

Promises aren't well supported at the moment but you can use a library. It will add a little bulk to your page for sure though.


A nice solution

(function (f,i) {
    do(i++,f)
}(function (f,i) {
    asyncFunction(someArray[i]);
    asyncFunction.done = function () {
        if (i++ === someArray.length - 1) {
            // Done
        } else { f(i) }
    };
}, 0)
like image 55
Downgoat Avatar answered Feb 11 '23 23:02

Downgoat


Many libraries have .all resolver:

  • jQuery
  • q
  • bluebird
  • and many more - https://promisesaplus.com/implementations

You can use them or learn their source code.

Assuming the code to be the body of function foo() :

function foo() {
    return Promise.all(someArray.map(function(item) {
        //other stuff here
        return asyncFunction(item, /* other params here */);
    }));
}

Or, if there's no other stuff to do, and no other params to pass :

function foo() {
    return Promise.all(someArray.map(asyncFunction));
}
like image 40
Artem Avatar answered Feb 11 '23 23:02

Artem