Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to execute promises sequentially, passing the parameters from an array?

Tags:

javascript

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?

like image 833
David Alsh Avatar asked Mar 29 '17 01:03

David Alsh


People also ask

How do you resolve promises sequentially?

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.

Does promise all run sequentially?

all() method executed by taking promises as input in the single array and executing them sequentially.

How do you iterate a promise?

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.


2 Answers

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()  )
like image 97
Ry- Avatar answered Sep 25 '22 16:09

Ry-


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.

like image 43
jdh8 Avatar answered Sep 23 '22 16:09

jdh8