var myArray = [1, 2, 3, 4, 5, 6] function myPromise(num){ return new Promise(res => { window.setTimeout(()=>{ res( console.log("done: " + num) ) },2000) }) } myPromise(myArray[0]) .then(x => myPromise(myArray[1])) .then(x => myPromise(myArray[2])) .then(x => myPromise(myArray[3])) .then(x => myPromise(myArray[4])) .then(x => myPromise(myArray[5]))
Right now, if I execute the statement above, it will run sequentially. In my actual use case the array is dynamically populated and I need to execute the myPromise()
function for each member in myArray
.
How can I make a "pauseable loop" that will loop for each item in the array, execute myPromise
and wait for the promise to be resolved before continuing to the next iteration?
The essence of this function is to use reduce starting with an initial value of Promise. resolve([]) , or a promise containing an empty array. This promise will then be passed into the reduce method as promise . This is the key to chaining each promise together sequentially.
all() method executed by taking promises as input in the single array and executing them sequentially.
To use Javascript promises in a for loop, use async / await . This waits for each promiseAction to complete before continuing to the next iteration in the loop. In this guide, you learn how async/await works and how it solves the problem of using promises in for loops.
You can make the repeated application of .then
into a fold pretty neatly if you’re okay with creating as many promises as array elements as is the case in the question:
myArray.reduce( (p, x) => p.then(_ => myPromise(x)), Promise.resolve() )
but an async function, for example, doesn’t require that:
const mapSeries = async (iterable, action) => { for (const x of iterable) { await action(x) } } mapSeries(myArray, myPromise)
which is built into the excellent promise library Bluebird as mapSeries
:
Promise.mapSeries(myArray, myPromise)
Runnable snippet:
const myArray = [1, 2, 3, 4, 5, 6] const sleep = ms => new Promise(res => { setTimeout(res, ms) }) const myPromise = num => sleep(500).then(() => { console.log('done: ' + num) }) myArray.reduce( (p, x) => p.then(_ => myPromise(x)), Promise.resolve() )
Don't create an array of promises. Create an array of functions returning a promise.
const f = x => new Promise(resolve => setTimeout(() => resolve(console.log(x)), 2000)) (async () => { for (let job of [1, 2, 3, 4, 5, 6].map(x => () => f(x))) await job() })()
Promises start running immediately after creation. Therefore, sequential execution is ensured by constructing the next promise only after finishing the current one.
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