Execute Asynchronous Functions in Parallel

Updated on 26 May, 2025
Execute Asynchronous Functions in Parallel header image

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: promise should 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 array functions.

  • Rejection Scenario: promise should 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

  • functions is an array of functions that returns promises
  • 1 <= functions.length <= 10

Approach and Intuition

Given the constraints and explanations in the examples, let's construct the approach to solve this problem:

  1. Initialization of Variables:

    • Create an array to store the results of the promises.
    • Initiate a counter to keep track of completed promises.
  2. Handling Each Function:

    • Iterate over the array of functions.
    • Immediately invoke each function (since they are asynchronous and return promises).
    • Attach .then and .catch handlers to each promise returned by the functions.
  3. Resolve Handling:

    • In the .then handler, 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 promise should resolve with the array of results.
  4. Reject Handling:

    • In the .catch handler, immediately reject the main promise with the encountered error, if it is the first to fail.
    • Ensure to handle synchronization issues to avoid multiple rejections.
  5. 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
js
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 Promise which takes two functions as arguments, resolve and reject.
  • Verify if the passed promisesArray is empty. If it is, immediately resolve the promise with an empty array as there are no functions to execute.
  • Create an array results of the same size as promisesArray with all elements initially set to null, to store the results of each promise.
  • Define a counter completionCount to keep track of how many promises have been resolved.
  • Iterate over promisesArray using forEach, executing each promise.
  • Inside the then block of each promise, store the resultant value at the corresponding index in the results array and increment completionCount.
  • Continuously check if completionCount matches the length of promisesArray. Once all promises are resolved, use resolve(results) to return the array of results from all the promises.
  • Handle any promise rejections with the catch block. Utilize reject(error) to throw an error out of the executeAllPromises function 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.

Comments

No comments yet.