I'm trying to put a delay between each iteration in a loop using async await. I've got a helper sleep function:
const sleep = ms => {
return new Promise(resolve => {
setTimeout(resolve, ms);
});
}
And this is correctly waiting between each loop:
for (let i = 0; i < 5; i++) {
console.log('waiting')
await sleep(1000)
}
However, this is not waiting between each loop:
[0, 1, 2, 3, 4].forEach(async () => {
console.log('waiting')
await sleep(1000)
});
How can I modify the forEach code block to behave as the regular for loop block with delays between each iteration of the for loop?
You could theoretically build up a promise chain, thats slightly more beautiful with reduce, but the same pattern can also be done with forEach:
[0, 1, 2, 3, 4].reduce(async (previous) => {
await previous;
console.log('waiting')
await sleep(1000)
});
But ... why not just use a for loop?
If you prefer methods rather than loops (which I usually do just aesthetically) you could pull in a third party module I maintain called async-af.
Among other things, it provides an asynchronous-friendly sequential forEach:
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
AsyncAF([0, 1, 2, 3, 4]).series.forEach(async () => {
console.log('waiting');
await sleep(1000);
});
<script src="https://unpkg.com/[email protected]/index.js"></script>
Of course, you could also just use a simple for...of loop:
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
(async () => {
for (const _ of [0, 1, 2, 3, 4]) {
console.log('waiting');
await sleep(1000);
}
})();
As for why Array.prototype.forEach doesn't work the way you'd expect, take this overly simplified implementation (here's a fuller one):
const forEach = (arr, fn) => {
for (let i = 0; i < arr.length; i++) {
// nothing is awaiting this function call
fn(arr[i], i, arr);
// i is then synchronously incremented and the next function is called
}
// return undefined
};
forEach([0, 1, 2, 3, 4], async () => {
console.log('waiting');
await delay(1000);
});
As you can see, Array.prototype.forEach synchronously calls the given callback function on each element. That's why you see all five waiting logs almost immediately. See this question for more information.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With