0

I have a loop that calls several sync functions simultaneously and in parallel. When they are all done, a series of final operations must be called to end the program.

For example, look at this simple code:

(async () => {
    var items = [1, 2, 3, 4, 5];

    for (var item of items) {
        console.log('Running... #' + item);
        
        var loop = async function(item) {
            var delay = getRandom(3, 7)*1000;
            await sleep(delay);
            console.log('Done. #' + item + ' with delay: ' + delay);
        }

        loop(item);
    }

    //while (true) {await sleep(1000);}

    console.log('Finish');

})();

///////////////////////////////////////

async function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}
function getRandom(min, max) {
    min = Math.ceil(min);
    max = Math.floor(max);
    return Math.floor(Math.random() * (max - min + 1) + min);
}

The output is as follows:

Running... #1
Running... #2
Running... #3
Running... #4
Running... #5
Finish
Done. #5 with delay: 3000
Done. #2 with delay: 4000
Done. #4 with delay: 6000
Done. #1 with delay: 7000
Done. #3 with delay: 7000

Which is not good, because "Finish" is printed before the end of all the loops.
Note that "Finish" is an example, and here I may have final operations such as closing a database or browser, and so on.

If I call the functions like this:

await loop(item);

Result:

Running... #1
Done. #1 with delay: 3000
Running... #2
Done. #2 with delay: 7000
Running... #3
Done. #3 with delay: 6000
Running... #4
Done. #4 with delay: 6000
Running... #5
Done. #5 with delay: 5000
Finish

The phrase "Finish" is printed well at the end, but instead all my functions are executed async and in order, which is not desirable.

Another way I tried is to use an infinite While similar to the one I commented on in the source code:

while (true) {await sleep(1000);}

Result:

Running... #1
Running... #2
Running... #3
Running... #4
Running... #5
Done. #1 with delay: 3000
Done. #5 with delay: 4000
Done. #3 with delay: 6000
Done. #4 with delay: 6000
Done. #2 with delay: 7000

The operation is correct here, but it never reaches "Finish".

Another way I thought of was to put a counter at the end of the functions and put a condition inside the end loop to control it and exit the loop.

like this:

(async () => {
    var items = [1, 2, 3, 4, 5];
    
    var n = 0; // <====
    for (var item of items) {
        console.log('Running... #' + item);
        
        var loop = async function(item) {
            var delay = getRandom(3, 7)*1000;
            await sleep(delay);
            console.log('Done. #' + item + ' with delay: ' + delay);
            n++; // <====
        }
    
        loop(item);
    }
    
    while (true) {
        await sleep(1000);
        if (n == items.length) break; // <====
    }
    
    console.log('Finish');
    
})();

And its output:

Running... #1
Running... #2
Running... #3
Running... #4
Running... #5
Done. #2 with delay: 3000
Done. #1 with delay: 4000
Done. #5 with delay: 4000
Done. #3 with delay: 5000
Done. #4 with delay: 6000
Finish

This is my expected and desired output. But I think the solution is not clean! Because the counter is difficult to control in the program, and maybe in some places I needed to return from the function and I should always be careful to increase n by one.

So I think there should be a simpler and more principled solution to achieve this goal. Maybe, for example, putting all the call results in an array and checking it in While, but as much as possible I do not want to change the structure of my program, and it is better to add everything simply and at the end of the code.

Do you have a solution?

Nabi K.A.Z.
  • 9,887
  • 6
  • 59
  • 81
  • 1
    See the linked question's answers. Short version: ```await Promise.all(items.map(async (item) => { /*...code using `await`...*/ }));``` – T.J. Crowder Apr 26 '22 at 13:07
  • 1
    Consider Promise.all. Check https://stackoverflow.com/questions/45285129/any-difference-between-await-promise-all-and-multiple-await – James Apr 26 '22 at 13:08

0 Answers0