You could 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 simplistic approach won't work if you have a promise which can error, or if you need previous results, so you might want to make sequencePromises more generic:
function genericSequencePromises(promiseFunction) { return (promise, parameter) => { return new Promise((resolve, reject) => return promiseFunction(resolve, reject, promise, parameter)); } }
Then you can do whatever you want as long as you return a Promise.
Finally, you might benefit from this little helper:
function promiseSeries(array, reducer) { return array.reduce(reducer, Promise.resolve()); }
Bringing it all together:
let sequencePromises = genericSequencePromises((resolve, reject, promise, num) => { resolve(promise.then(_ => console.log(`done: ${num}`))); } promiseSeries(myArray, sequencePromises);
This way, you can not only handle the case in your question, but much more complex cases.