HTML: Markup language
CSS: Styling language
JavaScript: Scripting language
Web APIs: Programming interfaces
All web technology
Learn web development
Discover our tools
Get to know MDN better
Since January 2024, this feature works across the latest devices and browser versions. This feature might not work in older devices or browsers.
The Array.fromAsync() static method creates a new, shallow-copied Array instance from an async iterable, iterable, or array-like object.
Array.fromAsync()
Array
Array.fromAsync(items) Array.fromAsync(items, mapFn) Array.fromAsync(items, mapFn, thisArg)
items
An async iterable, iterable, or array-like object to convert to an array.
mapFn
A function to call on every element of the array. If provided, every value to be added to the array is first passed through this function, and mapFn's return value is added to the array instead (after being awaited). The function is called with the following arguments:
element
The current element being processed in the array. If items is a sync iterable or array-like object, then all elements are first awaited, and element will never be a thenable. If items is an async iterable, then each yielded value is passed as-is.
index
The index of the current element being processed in the array.
thisArg
Value to use as this when executing mapFn.
this
A new Promise whose fulfillment value is a new Array instance.
Promise
Array.fromAsync() lets you create arrays from:
ReadableStream
AsyncGenerator
Map
Set
length
Array.fromAsync() iterates the async iterable in a fashion very similar to for await...of. Array.fromAsync(items) is generally equivalent to the following code, if items is an async iterable or sync iterable:
for await...of
Array.fromAsync(items)
const result = []; for await (const element of items) { result.push(element); }
Array.fromAsync() is almost equivalent to Array.from() in terms of behavior, except the following:
Array.from()
Array.fromAsync() and Promise.all() can both turn an iterable of promises into a promise of an array. However, there are two key differences:
Promise.all()
const asyncIterable = (async function* () { for (let i = 0; i < 5; i++) { await new Promise((resolve) => setTimeout(resolve, 10 * i)); yield i; } })(); Array.fromAsync(asyncIterable).then((array) => console.log(array)); // [0, 1, 2, 3, 4]
When items is an async iterable where each result's value is also a promise, then those promises are added to the resulting array without being awaited. This is consistent with the behavior of for await...of.
value
function createAsyncIter() { let i = 0; return { [Symbol.asyncIterator]() { return { async next() { if (i > 2) return { done: true }; i++; return { value: Promise.resolve(i), done: false }; }, }; }, }; } Array.fromAsync(createAsyncIter()).then((array) => console.log(array)); // (3) [Promise, Promise, Promise]
Note: In practice, you will rarely encounter an async iterable that yields promises, because if you implement it using an async generator function, then the yield expression automatically unwraps promises.
yield
Array.fromAsync( new Map([ [1, 2], [3, 4], ]), ).then((array) => console.log(array)); // [[1, 2], [3, 4]]
Array.fromAsync( new Set([Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)]), ).then((array) => console.log(array)); // [1, 2, 3]
Array.fromAsync({ length: 3, 0: Promise.resolve(1), 1: Promise.resolve(2), 2: Promise.resolve(3), }).then((array) => console.log(array)); // [1, 2, 3]
When items is a sync iterable or array-like object, both the input and output of mapFn are awaited internally by Array.fromAsync().
function delayedValue(v) { return new Promise((resolve) => setTimeout(() => resolve(v), 100)); } Array.fromAsync( [delayedValue(1), delayedValue(2), delayedValue(3)], (element) => delayedValue(element * 2), ).then((array) => console.log(array)); // [2, 4, 6]
When items is an async iterable, the input to mapFn is not awaited, but the output is. Using the same createAsyncIter function as above:
createAsyncIter
Array.fromAsync(createAsyncIter(), async (element) => (await element) * 2).then( (array) => console.log(array), ); // [2, 4, 6]
Curiously, this means that Array.fromAsync(createAsyncIter()) is not equivalent to Array.fromAsync(createAsyncIter(), (element) => element), because the latter awaits each yielded value, while the former does not.
Array.fromAsync(createAsyncIter())
Array.fromAsync(createAsyncIter(), (element) => element)
Array.fromAsync(createAsyncIter(), (element) => element).then((array) => console.log(array), ); // [1, 2, 3]
Array.fromAsync() awaits each value yielded from the object sequentially. Promise.all() awaits all values concurrently.
function* makeIterableOfPromises() { for (let i = 0; i < 5; i++) { yield new Promise((resolve) => setTimeout(resolve, 100)); } } (async () => { console.time("Array.fromAsync() time"); await Array.fromAsync(makeIterableOfPromises()); console.timeEnd("Array.fromAsync() time"); // Array.fromAsync() time: 503.610ms console.time("Promise.all() time"); await Promise.all(makeIterableOfPromises()); console.timeEnd("Promise.all() time"); // Promise.all() time: 101.728ms })();
Similar to for await...of, if the object being iterated is a sync iterable, and an error is thrown while iterating, the return() method of the underlying iterator will not be called, so the iterator is not closed.
return()
function* generatorWithRejectedPromises() { try { yield 0; yield Promise.reject(new Error("error")); } finally { console.log("called finally"); } } (async () => { try { await Array.fromAsync(generatorWithRejectedPromises()); } catch (e) { console.log("caught", e); } })(); // caught Error: error // No "called finally" message
If you need to close the iterator, you need to use a for...of loop instead, and await each value yourself.
for...of
await
(async () => { const arr = []; try { for (const val of generatorWithRejectedPromises()) { arr.push(await val); } } catch (e) { console.log("caught", e); } })(); // called finally // caught 3
Enable JavaScript to view this browser compatibility table.
Array.fromAsync
core-js
Array()
Array.of()