6

Lets say I have an array of promises. Each element of my array is a knex.js query builder and is ready to be executed and returns a promise.

How can I run each element of this array sequentially. The array is built dynamically.

let promisesArray = [q1,q2,q3] ;

Each q is not a promise by itself but it will return a promise upon execution.

Salar
  • 5,305
  • 7
  • 50
  • 78

5 Answers5

5

Here could be a possible option:

let p = Promise.resolve([]);
promisesArray.forEach(q => {
  p = p.then(responses => {
    //based on the nature of each q, to start execution
    //use either q().then() or q.then()
    return q().then(response => {
      //Any further logic can be here.
      console.log(response);
      return responses.concat([response]);
    })
  })
})

p.then(responses => {
  // here you have all of the responses.
})
Amin Fazlali
  • 1,209
  • 1
  • 9
  • 17
1

You can use Array.reduce to reduce the Array into one promise that chains them one after another

let promisesArray = [q1,q2,q3] ;

function runSequentially(promiseArr) {
  return promiseArr.reduce((accum, p) => accum.then(p), Promise.resolve())
}

//Example, this prints.. 1, 2, 3 then "done".
runSequentially([Promise.resolve(1).then(console.log), Promise.resolve(2).then(console.log), Promise.resolve(3).then(console.log)]).then(() => console.log("done"))
Khaled Osman
  • 1,251
  • 12
  • 17
0

I can think of bluebird promise, which should solve your issue. Keeping the concurrency value to 1, should execute promises sequentially.

    var Promise = require("bluebird");
    Promise.map([q1,q2,q3], {concurrency: 1})
Sreehari
  • 1,328
  • 11
  • 29
0

Based on your claim that q1, q2, q3 are "knex.js query builder and is ready to be executed and returns a promise", get a function to execute itself with the next index when the promise is resolved. Call it with 0 first.

function awaitPromise(arr, idx) {

   arr[idx]().then(function(res) {

       console.log(res);

       if (idx < arr.length - 1)      
           awaitPromise(arr, idx + 1);
   })
}
Charlie
  • 22,886
  • 11
  • 59
  • 90
0

If you're using bluebird, you can use Promise.map with concurrency set to 1.

await Promise.map(arrayOfObj, async (obj) => {
    await this.someOperation();
  },
  {concurrency: 1}
);
Deilan
  • 4,740
  • 3
  • 39
  • 52