Array.fromAsync()
The async sibling of Array.from. It accepts async iterables, awaits every element, and — unlike Promise.all — pulls them strictly in order.
Demo
Each input is [outcome, value, delay in ms]: 'ok' fulfils with the value, anything else rejects with an Error carrying it. Every element is awaited and the resolved values are collected in input order — where plain Array.from would hand back the promises themselves, unawaited. A rejection anywhere rejects the whole call. Because these promises were all created up front they run concurrently; with a lazy source such as an async generator, fromAsync would pull them strictly one at a time.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| source | async iterable | iterable | array-like | yes | An async iterable, a sync iterable, or an array-like. Sync sources still have each element awaited. |
| mapFn | Function | no (none) | Called as mapFn(element, index) after the element is awaited. May itself be async — its result is awaited too. |
| thisArg | any | no (undefined) | Value of `this` inside mapFn. |
Return value
Promise<Array> — A Promise resolving to a new array. Rejects with the first error thrown by the source, the mapFn, or any element that rejects.
Common patterns
const chunks = await Array.fromAsync(readable);
const results = await Array.fromAsync(promises);
const bodies = await Array.fromAsync(urls, u => fetch(u).then(r => r.text()));
Examples
Pitfalls
const a = Array.fromAsync(src); a.length
const a = await Array.fromAsync(src);
await Array.fromAsync(slowGenerator())
await Promise.all(urls.map(fetch))
await Array.fromAsync(mixed)
await Array.fromAsync(src, p => p.then(v => ({ok: true, v}), e => ({ok: false, e})));
await Array.fromAsync(endlessStream)
for await (const x of endlessStream) { if (done(x)) break; }
Array.fromAsync(src)
const out = []; for await (const x of src) out.push(x);
When to use
- Draining a finite async iterable into an array
- Collecting the output of an async generator
- Awaiting a list of values where order of resolution matters
- Mapping asynchronously while collecting, in one pass
- You want maximum concurrency → Promise.all over a mapped array
- You need every outcome including failures → Promise.allSettled
- The source is synchronous and holds no promises → Array.from
- The stream is infinite or huge → for await with a break, and process as you go
Notes
FAQ
Promise.all takes an array of promises that are already running and waits for all of them concurrently. Array.fromAsync pulls from an iterable one element at a time and awaits each before asking for the next. Over an array of existing promises the two finish together; over a lazy async generator, fromAsync is genuinely serial because nothing starts until it is requested.
await Promise.all(promises); // concurrent await Array.fromAsync(promises); // in order, same elapsed time here await Array.fromAsync(gen()); // strictly one at a time