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