
Problem Statement
In this problem, you are provided with an array named functions, wherein each element of this array is an asynchronous function that returns a promise. The task is to process these functions in parallel and track their completions. The output should be a new promise, promise, that handles the results from each of the asynchronous functions in the array.
Resolution Scenario:
promiseshould resolve if all the asynchronous functions resolve their promises successfully. The result should be an array containing the resolved values of these promises, maintaining the same order as they appear in the input arrayfunctions.Rejection Scenario:
promiseshould reject if any of the asynchronous function's promises get rejected. Additionally, the rejection reason should be the reason provided by the first promise that gets rejected.
Importantly, the challenge specifies not to use the built-in Promise.all function, which typically handles such scenarios, hence requiring a manual implementation of promise handling.
Examples
Example 1
Input:
functions = [ () => new Promise(resolve => setTimeout(() => resolve(5), 200)) ]
Output:
{"t": 200, "resolved": [5]}Explanation:
promiseAll(functions).then(console.log); // [5] The single function was resolved at 200ms with a value of 5.
Example 2
Input:
functions = [
() => new Promise(resolve => setTimeout(() => resolve(1), 200)),
() => new Promise((resolve, reject) => setTimeout(() => reject("Error"), 100))
]Output:
{"t": 100, "rejected": "Error"}Explanation:
Since one of the promises rejected, the returned promise also rejected with the same error at the same time.
Example 3
Input:
functions = [ () => new Promise(resolve => setTimeout(() => resolve(4), 50)), () => new Promise(resolve => setTimeout(() => resolve(10), 150)), () => new Promise(resolve => setTimeout(() => resolve(16), 100)) ]
Output:
{"t": 150, "resolved": [4, 10, 16]}Explanation:
All the promises resolved with a value. The returned promise resolved when the last promise resolved.
Constraints
functionsis an array of functions that returns promises1 <= functions.length <= 10
Approach and Intuition
Given the constraints and explanations in the examples, let's construct the approach to solve this problem:
Initialization of Variables:
- Create an array to store the results of the promises.
- Initiate a counter to keep track of completed promises.
Handling Each Function:
- Iterate over the array of functions.
- Immediately invoke each function (since they are asynchronous and return promises).
- Attach
.thenand.catchhandlers to each promise returned by the functions.
Resolve Handling:
- In the
.thenhandler, update the results array with the resolved value at the respective index. - Increment the counter of completed promises.
- If the counter indicates all promises are resolved, the main
promiseshould resolve with the array of results.
- In the
Reject Handling:
- In the
.catchhandler, immediately reject the mainpromisewith the encountered error, if it is the first to fail. - Ensure to handle synchronization issues to avoid multiple rejections.
- In the
Concurrency Assurance:
- All functions are triggered in the same synchronous loop, ensuring they run in parallel.
- JavaScript’s event loop and the inherent nature of promises handle the concurrency.
By following these steps, one can mimic what Promise.all offers but with explicit control over its internal workings, appropriately handling all given conditions from the problem statement.
Solutions
- JavaScript
var executeAllPromises = function(promisesArray) {
return new Promise((resolve, reject) => {
if(promisesArray.length === 0) {
resolve([]);
return;
}
const results = new Array(promisesArray.length).fill(null);
let completionCount = 0;
promisesArray.forEach((promise, index) => {
promise().then((result) => {
results[index] = result;
completionCount++;
if(completionCount === promisesArray.length) {
resolve(results);
}
}).catch((error) => {
reject(error);
})
});
});
};
The provided JavaScript solution demonstrates how to execute multiple asynchronous functions in parallel and gather their results. Utilize the executeAllPromises function by passing an array of asynchronous functions (promises) that you intend to execute concurrently.
- Begin by initiating a new
Promisewhich takes two functions as arguments,resolveandreject. - Verify if the passed
promisesArrayis empty. If it is, immediately resolve the promise with an empty array as there are no functions to execute. - Create an array
resultsof the same size aspromisesArraywith all elements initially set tonull, to store the results of each promise. - Define a counter
completionCountto keep track of how many promises have been resolved. - Iterate over
promisesArrayusingforEach, executing each promise. - Inside the
thenblock of each promise, store the resultant value at the corresponding index in theresultsarray and incrementcompletionCount. - Continuously check if
completionCountmatches the length ofpromisesArray. Once all promises are resolved, useresolve(results)to return the array of results from all the promises. - Handle any promise rejections with the
catchblock. Utilizereject(error)to throw an error out of theexecuteAllPromisesfunction if any individual promise fails.
This implemention ensures all provided asynchronous operations proceed in parallel, without wait time between them, resulting in efficient execution and handling of multiple asynchronous events. Use this function to manage groups of asynchronous operations that can run concurrently while gathering all their outcomes once all have completed.