简体   繁体   中英

How to wait for a loop with promises to complete to execute a method?

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

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'); });

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');
})

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'));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM