2721. Execute Asynchronous Functions in Parallel Solution
IntuitionThis problem is about executing multiple asynchronous functions in parallel and returning their results in order. The challenge is similar to JavaScrip
# **Intuition**  

This problem is about **executing multiple asynchronous functions in parallel** and returning their results in order. The challenge is similar to JavaScript's `Promise.all()`, which takes an array of promises and resolves when all promises have completed successfully or rejects if any promise fails.  

To achieve this, we need to handle asynchronous execution, store results in order, and track completion efficiently.  

---

# **Understanding Parallel Execution & Promises**  

✅ **What is Parallel Execution?**  
Parallel execution allows multiple asynchronous functions to run simultaneously instead of waiting for one to finish before starting another.  

✅ **What is `Promise.all()`?**  
`Promise.all()` takes an array of promises and returns a single promise that resolves when all promises are fulfilled or rejects if any promise fails.  

🔹 **Key Characteristics of Parallel Execution:**  
- **All functions start simultaneously** instead of waiting for each other.  
- **Order of execution doesn’t matter**, but the final results must maintain input order.  
- **If any function fails, the entire execution fails immediately.**  

---

# **Approach**  

I explored **two different approaches** to executing multiple asynchronous functions in parallel while preserving their order:  

---

# 🔹 **Approach 1: Using a `for` loop with manual tracking**  

```js
var promiseAll = function(functions) {
    return new Promise((res, rej) => {
        let results = [];
        let counter = 0;
        let len = functions.length;

        if (len === 0) {
            res(results);
        }

        for (let i = 0; i < len; i++) {
            functions[i]().then((result) => {
                results[i] = result;
                counter++;

                if (counter === len) {
                    res(results);
                }
            }).catch((err) => {
                rej(err);
            });
        }
    });
};
```

📌 **Explanation:**  

- We create a new `Promise` to manage parallel execution.  
- A `results` array stores the resolved values in order.  
- We track the number of completed functions using `counter`.  
- If all functions resolve, we return `results`.  
- If any function rejects, we immediately reject the main promise.  

✅ **Pros:**  
- Works efficiently for a known set of async functions.  
- Uses a simple loop to track execution and maintain order.  

---

# 🔹 **Approach 2: Using `forEach()` for cleaner execution**  

```js
var promiseAll = function(functions) {
    return new Promise((res, rej) => {
        let results = [];
        let counter = 0;
        let len = functions.length;

        if (len === 0) {
            res(results);
        }

        functions.forEach((fn, index) => {
            fn().then((val) => {
                results[index] = val;
                counter++;

                if (counter === len) {
                    res(results);
                }
            }).catch((err) => {
                rej(err);
            });
        });
    });
};
```

📌 **Differences from Approach 1:**  
- Uses `forEach()` instead of a `for` loop for better readability.  
- The logic remains the same but is slightly more concise.  

✅ **Pros:**  
- More readable and idiomatic JavaScript.  
- Easy to understand and maintain.  

---

# **Complexity Analysis**  

- **Time Complexity:**  
  - **Best case:** $$O(n)$$ – All promises resolve in parallel.  
  - **Worst case:** $$O(n)$$ – Still parallel, but affected by the slowest promise.  
- **Space Complexity:**  
  - $$O(n)$$ – Additional space for storing results.  

---

![image.png](https://assets.leetcode.com/users/images/600d4a29-e2e2-478b-8720-1c2289e049de_1743604001.869773.png)

---

# **Code Implementation**  

```js
/**
 * @param {Array<Function>} functions
 * @return {Promise<any>}
 */
var promiseAll = function(functions) {
    return new Promise((res, rej) => {
        let results = [];
        let counter = 0;
        let len = functions.length;

        if(len === 0){
            res(results);
        }

        functions.forEach((fn, index) => {
            fn().then((val)=> {
                results[index] = val;
                counter++;

                if(counter === len){
                    res(results);
                } 
            }).catch((err) => {
                rej(err);
            })
        })
    })    
};

/**
 * const promise = promiseAll([() => new Promise(res => res(42))])
 * promise.then(console.log); // [42]
 */
```

---

# **Important Topics to Learn 📚**  

- **JavaScript Promises**: Handling asynchronous operations.  
- **Promise.all()**: Executing multiple promises in parallel.  
- **Parallel Execution**: Running multiple functions simultaneously.  
- **forEach vs for Loop**: Understanding the differences in async behavior.  
- **Error Handling in Promises**: Handling failures properly in parallel execution.  

---

# 🚀 **Support & Feedback**  

✅ If you found this helpful, **please upvote & comment** on my solution!  
💬 Let’s discuss alternative solutions & improvements! 🚀
['JavaScript']