In an earlier post, I showed how to run a series of promises in serial and in batches of 5 (or any arbitrary batch size). Today, I want to show how to do this with reduce.
We will be using the same function that mocks our interactions with an external service:
const requestToExternalService = function(d) {
// Replace with a promise that does real work here...
return new Promise(resolve => {
console.log(d);
// Delay demonstrates we are indeed batching
setTimeout(resolve, 250);
});
};
We can use reduce like this to run multiple promises in serial:
// Replace with real data
const data = [...Array(5).keys()];
const promiseChain = data.reduce(
(chain, d) => chain.then(() => requestToExternalService(d)),
Promise.resolve()
);
We can also use reduce to batch the promises 5 at a time, but first we will need a helper function to break down our work:
const chunk = (array, batchSize = 5) => {
const chunked = [];
for(let i = 0; i < array.length; i += batchSize) {
chunked.push(array.slice(i, i + batchSize))
}
return chunked;
}
console.log(chunk([...Array(21).keys()]));
/*
* [ [ 0, 1, 2, 3, 4 ],
* [ 5, 6, 7, 8, 9 ],
* [ 10, 11, 12, 13, 14 ],
* [ 15, 16, 17, 18, 19 ],
* [ 20 ] ]
*/
With it, we can now use reduce to create our promise chain:
// Replace with real data
const chunkedData = chunk([...Array(21).keys()]);
const reducer = (chain, batch) => chain
.then(() => Promise.all(
batch.map(d => requestToExternalService(d))
));
const promiseChain = chunkedData.reduce(
reducer,
Promise.resolve()
);
Try it yourself: