Hone logo
Hone
Problems

Asynchronous Series Execution in JavaScript

This challenge focuses on implementing a function that executes an array of asynchronous functions sequentially, ensuring each function completes before the next one starts. This is a common pattern in JavaScript for tasks that depend on the results of previous asynchronous operations, such as fetching data in stages or processing items in a specific order. Successfully completing this challenge demonstrates understanding of asynchronous JavaScript and promises.

Problem Description

You are tasked with creating a function called asyncSeries that takes an array of asynchronous functions (functions that return Promises) as input and executes them in series. "Series" means that each function in the array must complete (resolve or reject) before the next function is executed. The asyncSeries function should return a Promise that resolves with an array containing the results of each function in the original order, or rejects if any of the functions reject.

Key Requirements:

  • Sequential Execution: Functions must be executed one after another.
  • Promise Handling: The input functions are expected to return Promises. asyncSeries must correctly handle these Promises.
  • Error Handling: If any of the asynchronous functions reject, asyncSeries should immediately reject with the same reason.
  • Result Accumulation: If all functions resolve successfully, asyncSeries should resolve with an array containing the resolved values of each function, in the same order as the input array.

Expected Behavior:

The asyncSeries function should accept an array of functions, each returning a Promise. It should execute these functions sequentially, waiting for each to complete before starting the next. The final resolved Promise should contain an array of the results from each function. If any function rejects, the entire asyncSeries Promise should reject with the rejection reason.

Edge Cases to Consider:

  • Empty Input Array: If the input array is empty, the function should resolve immediately with an empty array.
  • Functions that Don't Return Promises: While the problem specifies functions returning Promises, consider how your solution would behave if a function in the array didn't return a Promise. (Ideally, it should reject, but your solution doesn't need to explicitly handle this - the Promise wrapper will take care of it).

Examples

Example 1:

Input: [() => Promise.resolve(1), () => Promise.resolve(2), () => Promise.resolve(3)]
Output: [1, 2, 3]
Explanation: Each function resolves with a number. `asyncSeries` resolves with an array containing these numbers in order.

Example 2:

Input: [() => Promise.resolve(1), () => Promise.resolve(2), () => Promise.reject('Error')]
Output: Error
Explanation: The third function rejects with 'Error'. `asyncSeries` immediately rejects with the same error.

Example 3:

Input: []
Output: []
Explanation: The input array is empty. `asyncSeries` resolves immediately with an empty array.

Constraints

  • The input array will contain only functions.
  • Each function in the input array is expected to return a Promise.
  • The number of functions in the input array can range from 0 to 1000.
  • The resolution/rejection values of the Promises can be of any type.
  • Performance: The solution should execute efficiently, avoiding unnecessary overhead. While not a strict requirement, aim for a time complexity of O(n), where n is the number of functions in the input array.

Notes

Consider using async/await or .then() chaining to manage the asynchronous flow. Think about how to accumulate the results as you iterate through the functions. The key is to ensure that each function completes before the next one is started. Error handling is crucial – a single rejection should halt the entire series.

Loading editor...
javascript