We use cookies (including Google cookies) to personalize ads and analyze traffic. By continuing to use our site, you accept our Privacy Policy.

Execute Asynchronous Functions in Parallel

Number: 2807

Difficulty: Medium

Paid? No

Companies: Paytm


Problem Description

Given an array of asynchronous functions (each taking no arguments and returning a promise), execute all these functions concurrently. Return a new promise that resolves with an array of resolved values (in the same order as the original functions) if all asynchronous functions resolve successfully, or rejects immediately with the reason of the first rejection if any promise fails.


Key Insights

  • The problem requires parallel execution of multiple asynchronous functions.
  • The solution mimics the behavior of Promise.all without using the built-in function.
  • Create a container (e.g., an array) to hold the results at respective indices.
  • Keep track of how many promises have successfully resolved.
  • If any promise rejects, immediately reject the final promise with the encountered error.

Space and Time Complexity

Time Complexity: O(n) where n is the number of asynchronous functions (each function is launched concurrently). Space Complexity: O(n) for storing the resolved values as well as auxiliary variables.


Solution

We initiate execution for all asynchronous functions concurrently. For each function:

  1. Call it immediately to begin execution.
  2. For a successful resolution, store its result in a results container at the same index as its corresponding function.
  3. Increase a counter for resolved promises, and once the counter equals the number of functions, resolve the final promise with the results.
  4. If any promise rejects, immediately reject the final promise with that rejection reason. In this solution, synchronization is handled manually (using counters or atomic variables) without relying on built-in helper methods equivalent to Promise.all.

Code Solutions

import asyncio

# Define the promise_all function to execute asynchronous functions in parallel.
async def promise_all(functions):
    # Prepare a list to store results in the original order.
    results = [None] * len(functions)
    done = 0

    # Create a Future to be set when all functions complete or any fails.
    final_future = asyncio.Future()

    # This inner async function runs each function and handles its result.
    async def run_function(i, func):
        nonlocal done
        try:
            # Await the result from the asynchronous function.
            result = await func()
            results[i] = result  # store the result in order
            done += 1
            # If all functions have completed, set the final_future result.
            if done == len(functions) and not final_future.done():
                final_future.set_result(results)
        except Exception as e:
            # On the first failure, set exception for the future.
            if not final_future.done():
                final_future.set_exception(e)

    # Start all functions concurrently.
    for i, func in enumerate(functions):
        asyncio.create_task(run_function(i, func))
    return await final_future

# Example usage of promise_all.
async def main():
    functions = [
        lambda: asyncio.sleep(0.2, result=5)
    ]
    try:
        res = await promise_all(functions)
        print("Resolved:", res)
    except Exception as e:
        print("Rejected:", e)

# Run the async main function.
asyncio.run(main())
← Back to All Questions