Given an array of asynchronous functions functions, return a new promise promise. Each function in the array accepts no arguments and returns a promise. All the promises should be executed in parallel.
promise resolves:
functions were resolved successfully in parallel. The resolved value of promise should be an array of all the resolved values of promises in the same order as they were in the functions. The promise should resolve when all the asynchronous functions in the array have completed execution in parallel.promise rejects:
functions were rejected. promise should also reject with the reason of the first rejection.Please solve it without using the built-in Promise.all function.
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:
functions is an array of functions that returns promises1 <= functions.length <= 10In #2721 Execute Asynchronous Functions in Parallel, the goal is to run multiple asynchronous functions at the same time and return their results once all of them complete. Each function returns a promise, so the key idea is to trigger all promises immediately instead of waiting for each one sequentially.
A common strategy is to iterate through the list of functions and invoke them right away, storing their returned promises. Using a mechanism similar to Promise.all, you track when every promise resolves and store the results in their original order. If any promise rejects, the entire combined promise should reject immediately.
This approach ensures that all operations run concurrently, minimizing waiting time compared to sequential execution. The algorithm mainly involves promise handling, result indexing, and completion tracking. The time complexity is O(n) for managing the promises, while the space complexity is O(n) to store the resulting values and tracking state.
| Approach | Time Complexity | Space Complexity |
|---|---|---|
| Parallel execution using Promise tracking (similar to Promise.all) | O(n) | O(n) |
NeetCodeIO
This approach involves managing a counter to track resolved promises and ensuring we handle rejection immediately. We loop through each of the asynchronous functions, initiate their execution, and attach then and catch handlers. Using shared variables, we manage the resolved values and first rejection detection.
1function promiseAll(functions) {
2 return new Promise((resolve, reject) => {
3 let results = [];
4 let completed = 0;
5 functions.forEach((fn, index) => {
6 fn().then(value => {
7 results[index] = value;
8 completed++;
9 if (completed === functions.length) {
10 resolve(results);
11 }
12 }).catch(err => {
13 reject(err);
14 });
15 });
16 });
17}This code creates a promise that resolves when all asynchronous functions have resolved, or rejects immediately if any promise is rejected. We maintain a results array to store resolved values and a completed counter to know when all functions have resolved. Each function is called, and on success, we store its result and increment the completed counter. Upon completion of all functions, we resolve the promise with the results.
This approach focuses on using individual promise resolution for each function and using a shared state to track the first rejection or when all have completed.
1function promiseAll(functions) {
2 const results = new Array(functions.length
This approach manually handles the resolution and rejection of each promise returned by the functions. We'll iterate over the functions list, execute each one in parallel, and use counters or markers to determine when all promises have settled. Upon completion, their results will be consolidated into a single array, keeping track of the order.
Time Complexity: O(n) for n functions and promises.
Space Complexity: O(n) storing the resolved values.
1function promiseAll(functions) {
2 return new Promise((resolveHere, a counter is used to ensure all promises have resolved before resolving the overall promise. This approach maintains state using closure variables to track the number of resolved promises and collects results into predefined storage (array).
Time Complexity: O(n) because each promise executes independently.
Space Complexity: O(n) due to the results array storing each resolved value.
1function promiseAll(functions) {
2 return new Promise((resolve,Watch expert explanations and walkthroughs
Jot down your thoughts, approach, and key learnings
Running functions in parallel reduces overall waiting time because all operations start at once. Sequential execution would wait for one promise to finish before starting the next, increasing total runtime.
Yes, problems involving promises, concurrency, and asynchronous control flow are commonly discussed in JavaScript-focused interviews. Understanding how parallel execution works is particularly useful for frontend and Node.js roles.
An array is typically used to store the promises and their results. The array allows you to maintain the original order of execution results while tracking when each asynchronous operation completes.
The optimal approach is to invoke all asynchronous functions immediately and track their returned promises. By aggregating them using logic similar to Promise.all, you wait for every promise to resolve while preserving result order.
This solution initiates each asynchronous function, attaches promise handlers to manage results, and uses a counter to track the number of resolved promises. On the resolution of any promise, we store its result and increase the counter. If all are resolved, we resolve our overall promise with the results. Any rejection leads to an immediate promise rejection.