57

Given I have an async generator:

async function* generateItems() {
    // ...
}

What's the simplest way to iterate all the results into an array? I've tried the following:

// This does not work
const allItems = Array.from(generateItems());
// This works but is verbose
const allItems = [];
for await (const item of generateItems()) {
    allItems.push(item);
}

(I know this is potentially bad practice in a Production app, but it's handy for prototyping.)

4
  • 2
    This works but is verbose Don't think you can get any better than that, since every item needs to be awaited individually in order to get access to the next Promise Commented Nov 2, 2019 at 5:00
  • 16
    allItems = await generateItems().toArray() is currently proposed
    – Bergi
    Commented Jun 10, 2020 at 10:44
  • 6
    There’s a new Array.asyncFrom proposal that mentions this post. Commented Aug 9, 2021 at 20:08
  • NodeJS v22 and later supports Array.fromAsync ;)
    – vitaly-t
    Commented Aug 5, 2024 at 0:59

4 Answers 4

38

You can use the new Array.fromAsync() static method.

This will return a promise whose fulfillment value is a new Array instance.

Example from the ES proposal:

async function* f() {
  for (let i = 0; i < 4; i++) yield i;
}

// Resolves to [0, 1, 2, 3].
await Array.fromAsync(f());

Availability

Although it is still in stage 3, all major browsers and Node support it in their latest versions.

5
  • 7
    If anyone comes looking for the same information as me: this is not yet support in the latest Node as of writing, but is supported in Bun. Commented Jan 19, 2024 at 14:23
  • 3
    @TomáÅ¡ Hübelbauer, it might interest you to know that Node.js 22 or higher supports it. Commented Apr 25, 2024 at 16:28
  • Note that fromAsync is not a finished proposal. It's still stage 3 and thus not implemented in many environments: github.com/tc39/proposals Commented Sep 17, 2024 at 9:32
  • Now it is implemented in all major browsers and Node.
    – trincot
    Commented Dec 13, 2024 at 9:11
  • Available in Typescript with "lib": [..., "ESNext.Array"] in your tsconfig.json. Commented Jun 25 at 21:19
31

Here is a simple function to convert async iterator to an array without having to include a whole package.

async function toArray(asyncIterator){ 
    const arr=[]; 
    for await(const i of asyncIterator) arr.push(i); 
    return arr;
}
2
  • 1
    good one, same as implemented in accepted answer see on GitHub
    – piouson
    Commented Oct 25, 2020 at 13:22
  • 5
    Thanks for this, surprised to learn that it isn't a first-order concept... Commented Apr 1, 2021 at 23:29
17

Your solution is the only one I know of. Here it is as a TypeScript function:

async function gen2array<T>(gen: AsyncIterable<T>): Promise<T[]> {
    const out: T[] = []
    for await(const x of gen) {
        out.push(x)
    }
    return out
}

TypeScript Playground

2
  • do you have any idea why this has to be type-hinted for AsyncGenerator<T> specifically? I wanted a more general function that accepts AsyncIterator<T>, which is the base-type of AsyncGenerator<T> - but for some reason that doesn't work. Commented Sep 15, 2021 at 10:35
  • 2
    @mindplay.dk I think it works with AsyncIterable but not AsyncIterator. I added a TS Playground link -- does that do what you want?
    – mpen
    Commented Sep 15, 2021 at 20:26
-10

Looks like the async-iterator-to-array npm library does this:

Install

npm install --save async-iterator-to-array

Usage

const toArray = require('async-iterator-to-array')

async function * iterator (values) {
  for (let i = 0; i < values.length; i++) {
    yield values[i]
  }
}

const arr = await toArray(iterator([0, 1, 2, 3, 4]))

console.info(arr) // 0, 1, 2, 3, 4
3
  • 49
    Note that referenced package does it internally exactly the same way which OP marked as "verbose". Think of it, do you really need another dependency in your project?...
    – 1valdis
    Commented Jul 7, 2020 at 8:10
  • 7
    @1valdis Note that this answer is written by OP. Commented Mar 17, 2022 at 17:45
  • This package has been deprecated in favor of it-all Commented Apr 9, 2024 at 10:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.