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');
});