Hone logo
Hone
Problems

Concurrent Data Fetching Challenge

Many real-world applications need to fetch data from multiple sources simultaneously to improve performance and user experience. This challenge focuses on implementing a mechanism to execute asynchronous operations in parallel and collect their results efficiently.

Problem Description

Your task is to write a Javascript function fetchDataParallel that accepts an array of asynchronous functions (promises or functions that return promises). This function should execute all these asynchronous functions concurrently and return a promise that resolves with an array containing the results of each function, in the same order as the input array.

Key Requirements:

  • Parallel Execution: All provided asynchronous functions should start executing at the same time, without waiting for previous ones to complete.
  • Ordered Results: The returned array of results must correspond to the order of the functions in the input array. For instance, if the input is [asyncFn1, asyncFn2], the output should be [resultOfAsyncFn1, resultOfAsyncFn2].
  • Error Handling: If any of the asynchronous functions reject, the fetchDataParallel function should reject immediately with the error from the first function that rejected. Subsequent results or rejections should be ignored.
  • Return a Promise: The fetchDataParallel function itself must return a Promise.

Expected Behavior:

  • If all functions succeed, the returned promise resolves with an array of their resolved values.
  • If any function rejects, the returned promise rejects with the error of the first rejecting function.

Examples

Example 1:

const asyncOperation1 = () => new Promise(resolve => setTimeout(() => resolve("Result 1"), 100));
const asyncOperation2 = () => new Promise(resolve => setTimeout(() => resolve("Result 2"), 50));
const asyncOperation3 = () => new Promise(resolve => setTimeout(() => resolve("Result 3"), 150));

const operations = [asyncOperation1, asyncOperation2, asyncOperation3];

// Expected output will be a promise that resolves to:
// ["Result 1", "Result 2", "Result 3"]

Explanation: All three asynchronous operations are initiated. asyncOperation2 finishes first, then asyncOperation1, and finally asyncOperation3. The results are collected in the original order.

Example 2:

const failingOperation = () => new Promise((_, reject) => setTimeout(() => reject(new Error("Operation failed")), 75));
const successfulOperation = () => new Promise(resolve => setTimeout(() => resolve("Success"), 120));

const operations = [successfulOperation, failingOperation];

// Expected output will be a promise that rejects with:
// Error("Operation failed")

Explanation: Both operations start. failingOperation rejects before successfulOperation resolves. The fetchDataParallel function should reject immediately with the error from failingOperation.

Example 3:

const fastSuccess = () => Promise.resolve("Fast");
const slowSuccess = () => new Promise(resolve => setTimeout(() => resolve("Slow"), 200));
const anotherFastSuccess = () => Promise.resolve("Another Fast");

const operations = [fastSuccess, slowSuccess, anotherFastSuccess];

// Expected output will be a promise that resolves to:
// ["Fast", "Slow", "Another Fast"]

Explanation: Even though slowSuccess takes the longest, all operations are started concurrently. The results are still returned in the order of the original array.

Constraints

  • The input operations will be an array.
  • Each element in the operations array will be a function that returns a Promise, or a Promise itself.
  • The operations array can be empty.
  • The functions can take any number of arguments (though for this challenge, assume they take none for simplicity).

Notes

This problem is a common use case for Promise.all. Consider how you would implement this functionality from scratch if Promise.all were not available, or if you needed slightly different behavior (e.g., handling rejections differently). You'll need to manage multiple promises and their states.

Loading editor...
javascript