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

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.


Sequential:

you can use async await features to run promises sequentially . here's a snippet

async function chainPromiseCalls(asyncFunctions=[],respectiveParams=[]){

    for(let i=0;i<asyncFunctions.length;i++){
        const eachResult = await asyncFunctions[i](...respectiveParams[i]);
        // do what you want to do with each result 
       
    }

    return ;
}

Parallel:

for parallel you can just call each async function once in a loop , but if you do want to get their combined result , you can use Promise.all

function parallelPromiseCalls(asyncFunctions=[],respectiveParams=[]){
    return Promise.all(asyncFunctions.map((func,index)=>func(...respectiveParams[index])))
       .then(resultsList=>{
        resultsList.forEach((result,index)=>{
           // do what you want to do with each result in the list
        })
        return ;
    })
}


note : I am considering respective parameters as an list of lists since multiple parameters should be passed to any one of the function , else if you have to pass only a single parameter to each then you can remove the spread operator.


Also you can do it via recursive approach - executeSequentially calls itself:

function createPromise(x) {
  return new Promise(res => {
    setTimeout(() => {
      console.log(x)
      res(x);
    }, x * 1000)
  })
}

function executeSequentially(array) {  
  return createPromise(array.shift())
    .then(x => array.length == 0 ? x : executeSequentially(array));
}

console.time('executeSequentially');
executeSequentially([1, 2, 3]).then(x => {
  console.log('last value: ' + x);
  console.timeEnd('executeSequentially');
});