How to execute promises sequentially by passing parameters from an array?

var myArray = [1, 2, 3, 4, 5, 6] function myPrommise(num){ return new Promise(res => { window.setTimeout(()=>{ res( console.log("done: " + num) ) },2000) }) } myPrommise(myArray[0]) .then(x => myPrommise(myArray[1])) .then(x => myPrommise(myArray[2])) .then(x => myPrommise(myArray[3])) .then(x => myPrommise(myArray[4])) .then(x => myPrommise(myArray[5])) 

Right now, if I execute the above statement, it will run sequentially. In my actual use, the array is dynamically populated, and I need to execute the myPromise() function for each member in myArray .

How can I create an “intermittent loop” that will loop for each element in the array, execute myPromise and wait for the promise to be resolved before continuing with the next iteration?

+7
javascript
source share
4 answers

You can re-do the .then application in the fold:

 myArray.reduce( (p, x) => p.then(_ => myPromise(x)), Promise.resolve() ) 

Bluebird, a great promise library that you should use if you arent also has mapSeries built in :

 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() ) 
+16
source share

You can use Array.reduce .

 //type: [number] var myArray = [1, 2, 3, 4, 5, 6] //doesn't really matter //type: number -> Promise<number> function myPromise(num){ return new Promise((resolve) => { window.setTimeout(()=>{ resolve(console.log("done: " + num) ) },2000) }) } //Array.reduce has type: [a] ~> ((b, a) -> b), b) -> b //So it can have type: //[number] ~> ((Promise<number> -> number -> Promise<number>), Promise<number>) -> Promise<number> //Therefore we need to give reduce a function that takes a Promise //resolving to a number and a number which makes a new promise. //This is the function we want: function sequencePromises(promise, number) { return new Promise((resolve) => { resolve(promise.then(_ => myPromise(number))); } } myArray.reduce(sequencePromises, Promise.resolve()); 

Of course, this simplified approach will not work if you have a promise that might be a mistake, or if you need previous results, so you can make sequencePromises more general:

 function genericSequencePromises(promiseFunction) { return (promise, parameter) => { return new Promise((resolve, reject) => return promiseFunction(resolve, reject, promise, parameter)); } } 

Then you can do whatever you want while you return the promise.

Finally, you can use this little helper:

 function promiseSeries(array, reducer) { return array.reduce(reducer, Promise.resolve()); } 

Putting it all together:

 let sequencePromises = genericSequencePromises((resolve, reject, promise, num) => { resolve(promise.then(_ => console.log(`done: ${num}`))); } promiseSeries(myArray, sequencePromises); 

Thus, you can not only handle the matter in your question, but also much more complex cases.

+1
source share

I would use babel and do it like this:

  let args = [1, 2, 3]; const myPromise = async x => console.log('arg:',x); const test = async () => { for (let task of args.map(myPromise)) await task; } test().then(console.log('Done')); 
 <script src="https://unpkg.com/ babel-standalone@6.24.0 /babel.min.js"></script> 
0
source share

You can iterate over an array of elements and pass parameters as follows:

 const arr = [1, 2, 3, 4, 5, 6]; const MyPromiseFunction = num => new Promise((resolve, reject) => { // Your logic... setTimeout(() => num <= 4 ? resolve('Success!') : reject('Rejected!'), 1000 * num); }); const logMessage = (num, msg) => console.log(`For number ${num} promise result: ${msg}`); arr.forEach( num => MyPromiseFunction(num) .then(message => logMessage(num, message)) .catch(reason => logMessage(num, reason)) ); 
0
source share

All Articles