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.