Asynchronous Reduce in JavaScript


The reduce function is a powerful tool for processing arrays, but it can become tricky when dealing with asynchronous operations. In JavaScript, we can leverage async/await and promises to handle these operations gracefully. Let's imagine we're fetching data from multiple endpoints, each represented as a promise. To process them all using reduce, we'll need to handle each promise within the reduce callback:
async function asyncReduceExample() {
const promises = [
fetch('https://api.example.com/data1').then(res => res.json()),
fetch('https://api.example.com/data2').then(res => res.json()),
fetch('https://api.example.com/data3').then(res => res.json()),
];
const result = await promises.reduce(async (accumulator, currentPromise) => {
const acc = await accumulator;
const currentValue = await currentPromise;
return [...acc, currentValue];
}, Promise.resolve([]));
console.log(result);
}
Notice the use of async in the reduce callback, allowing us to use await to resolve each Promise before proceeding. The initial value of the accumulator is set using Promise.resolve([]) to ensure it's a promise that resolves to an empty array. This ensures that the reduce function handles the asynchronous operations correctly by resolving the accumulator before it is used in subsequent iterations. Each Promise is fetched in sequence, and the results are aggregated in the result array which is logged to the console.
For more complex scenarios, error handling is crucial. Here's a revised example that handles potential errors during the asynchronous operations:
async function asyncReduceWithErrorHandling() {
const promises = [
fetch('https://api.example.com/data1').then(res => res.json()),
fetch('https://api.example.com/data2').then(res => res.json()),
fetch('https://api.example.com/data3').then(res => res.json()),
];
try {
const result = await promises.reduce(async (accumulator, currentPromise) => {
const acc = await accumulator;
const currentValue = await currentPromise;
return [...acc, currentValue];
}, Promise.resolve([]));
console.log('Success:', result);
} catch (error) {
console.error('Error:', error);
}
}
Subscribe to my newsletter
Read articles from Hossein Margani directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
