Home > Back-end >  How to wait for a loop with promises to complete to execute a method?
How to wait for a loop with promises to complete to execute a method?

Time:03-31

I want to execute a loop with promises, but I want to execute a method only after the loop completes.

This is a similar example of that I want to do

const array = ['a', 'b', 'c'];

console.log('start');
array.forEach((i) => {
  setTimeout(()=> console.log(i), 3000);        
});
console.log('end');

this the result i got.

start
end
a
b
c

CodePudding user response:

It's easily doable with something like Promise.all once you know how.

The key is to create an array of Promises and then call Promise.all on it.

But before I can show we need to make some adjustments:

First let's wrap setTimeout to return a promise:

function delay(amount) {
    return new Promise((resolve) => {
        setTimeout(resolve, amount);
    });
}

Then change the code to push all created promises onto an array:

const array = ['a', 'b', 'c'];
let promises = [];

async function doSomething(i) {
    console.log(i);

    await delay(3000);
}

console.log('start');
array.forEach((i) => {
    const promise = doSomething(i);

    promises.push(promise);
});

Here doSomething is doing the asynchronous work.

Lastly, we wait for all Promises to be resolved with Promise.all:

await Promise.all(promises);

console.log('end');

Gives:

start
a
b
c
end

function delay(amount) {
    return new Promise((resolve) => {
        setTimeout(resolve, amount);
    });
}

const array = ['a', 'b', 'c'];
let promises = [];

async function doSomething(i) {
    console.log(i);

    await delay(3000);
}

console.log('start');
array.forEach((i) => {
    const promise = doSomething(i);

    promises.push(promise);
});

Promise.all(promises).then(() => {
  console.log('end');
});

CodePudding user response:

setTimeout is asynchronous, but is not thenable like a promise. If your direct question is to execute your code when all the timeouts end, then it should be done as follows:

const array = ['a', 'b', 'c'];
let numberOfTimeoutsToBeExecuted = array.length;
// keep track of the number of timeouts that have finished execution
let numberOfTimeoutsExecuted = 0;

console.log('start');
array.forEach((i) => {
  setTimeout(() => {
    console.log(i),
    numberOfTimeoutsExecuted  = 1;
    // execute your code when the last timeout has finished execution
    if (numberOfTimeoutsToBeExecuted === numberOfTimeoutsExecuted) {
      console.log('end');
    }
  }, 3000);       
});

However, if you want to wait for multiple promises to finish execution, the following is the best way to do this:

const array = ['a', 'b', 'c'];
const promises = [];

console.log('start');
array.forEach((i) => {
    // add all promises that will be executed into array
    promises.push(new Promise((resolve, reject) => {
      setTimeout(()=> {
        console.log(i);
        resolve();
      }, 3000);
    }));
});

// execute all promises here
Promise.all(promises).then(() => console.log('end'));

CodePudding user response:

One option is do the following:

const array = ['a', 'b', 'c'];

console.log('start');
const promises = [];
array.forEach((i) => {
    promises.push(new Promise(resolve => setTimeout(() => {
        console.log(i)
        resolve()
    }, 3000)))
})

Promise.all(promises).then(() => {
    console.log('end');
})
  • Related