- Published on
How to Implement Promise.all
- Authors
- Name
- Martin Karsten
- @mkdevX
The Promise.all Function
Promise.all is a built-in takes an array of promises as input and returns a new promise that resolves to an array of the resolved values of each promise,in the same order as the input promises.
The big advantage of using Promise.all is that Promises can be executed in parallel and don't block each other.
Promise.all([
fetch('/api/a'),
fetch('/api/b'),
fetch('/api/c')
]).then([responseA, responseB, responseC] => {
/// ...
});
Using Recursion
Promise.all = async function promiseAllRecursive(values) {
if (values.length === 0) return Promise.resolve([])
const [first, ...rest] = values
// ensures that first is a promise
const firstResult = await Promise.resolve(first)
const restResults = await promiseAllRecursive(rest)
return [firstResult, ...restResults]
}
How does the fuction above work?
argument values: Array of Promises and non Promises
Base Case
if (values.length === 0)
- we return a Promise that resolves with an empty array
- We create to variables
first
: The first value of the arrayrest
: An array with all the values of the array, except the first often
firstResult
: we await for the first value to resolve
Promise.resolve(first)
ensures that the value is a Promise- if values was an array only Promises, const
firstResult = await first
would be enough
restResults
: callspromiseAllRecursive
recursivly
- reduces the array to the point where the base case 1. is met
- we return an array with the first resolved value and the rest of resolved values
- becase this is an async function, the array implicitly is retunred as a Promise which resolves to the array
Recrusive Solution with Error Handling
async function promiseAllRecursiveWithErrorHandling(values) {
if (!Array.isArray(values)) {
return Promise.reject(new TypeError('Argument must be an array'))
}
if (values.length === 0) {
return Promise.resolve([])
}
try {
const [first, ...rest] = values
const firstResult = await Promise.resolve(first)
const restResults = await promiseAllRecursive(rest)
return [firstResult, ...restResults]
} catch (error) {
return Promise.reject(error)
}
}
Iterative Solution
async function promiseAllIterative(values) {
let results = []
for (let value of values) {
try {
let result = await Promise.resolve(value)
results.push(result)
} catch (error) {
throw error
}
}
return results
}
Solution using Array.reduce
function promiseAllReduce(values) {
return values.reduce(async (results, value) => {
const prevResults = results
const result = await Promise.resolve(value)
return [...prevResults, result]
}, Promise.resolve([]))
}
All of the implements above will lead to the same outcome.