How to Use Array.fromAsync in JavaScript

Array.fromAsync() is a built-in static method in JavaScript that creates a new array from an async iterable, a sync iterable, or an array-like object containing promises. This article explains how Array.fromAsync() operates, breaks down its syntax and parameters, details its sequential execution mechanism, and provides practical code examples demonstrating how it simplifies asynchronous data processing.

What is Array.fromAsync?

Array.fromAsync() acts as the asynchronous counterpart to Array.from(). While Array.from() works strictly with synchronous iterables and array-like objects, Array.fromAsync() handles objects that yield promises or implement the Symbol.asyncIterator protocol. Instead of returning an array immediately, it returns a Promise that resolves to a newly created array containing all resolved values.

Syntax and Parameters

The method accepts up to three arguments:

Array.fromAsync(asyncIterable, mapFn, thisArg)

How Array.fromAsync Builds Arrays Step-by-Step

When Array.fromAsync() is invoked, it processes values sequentially using the following steps:

  1. Iterate: It retrieves the iterator from the provided source (prioritizing Symbol.asyncIterator, then falling back to Symbol.iterator).
  2. Await Values: It reads items one by one. If an item is a promise, Array.fromAsync() pauses execution until that promise fulfills.
  3. Map Elements: If a mapping function (mapFn) is provided, the resolved item is passed to it. If the mapping function returns a promise, that promise is also awaited.
  4. Collect: The final value is appended to the resulting internal array.
  5. Resolve or Reject: Once the iterator completes (done: true), the main promise resolves with the populated array. If any iteration step, promise, or mapping function rejects, the returned promise immediately rejects with that error.

Practical Examples

1. Converting an Async Generator

Async generators yield values asynchronously. Array.fromAsync() can collect all yielded results into a standard array:

async function* fetchNumbers() {
  yield 1;
  yield 2;
  yield 3;
}

const numbers = await Array.fromAsync(fetchNumbers());
console.log(numbers); // Output: [1, 2, 3]

2. Resolving an Array of Promises

Unlike Array.from(), which would leave promises unresolved inside the resulting array, Array.fromAsync() awaits each promise:

const promiseArray = [
  Promise.resolve("apple"),
  Promise.resolve("banana"),
  Promise.resolve("cherry")
];

const fruits = await Array.fromAsync(promiseArray);
console.log(fruits); // Output: ['apple', 'banana', 'cherry']

3. Using an Async Mapping Function

You can transform items during iteration, even when the transformation itself is asynchronous:

const userIds = [1, 2, 3];

async function fetchUserName(id) {
  return `User_${id}`;
}

const users = await Array.fromAsync(userIds, async (id) => {
  return await fetchUserName(id);
});

console.log(users); // Output: ['User_1', 'User_2', 'User_3']

Array.fromAsync vs. Promise.all

While Promise.all(array.map(...)) executes promises concurrently, Array.fromAsync() consumes iterables sequentially. This sequential nature is critical when working with streams or async generators where the next value depends on the previous operation completing first, or when you need to avoid overwhelming a system with concurrent network requests.