Generator / Iterator / Iterable

Generator function

function* someNumberGenerator() { yield 1 yield 2 yield 3 yield 4 } const generatorObject = someNumberGenerator() generatorObject.next() // {value: 1, done: false} generatorObject.next() // {value: 2, done: false} generatorObject.next() // {value: 3, done: false} generatorObject.next() // {value: 4, done: false} generatorObject.next() // {value: undefined, done: true}

Generator function with return

function* someNumberGenerator() { yield 1 yield 2 yield 3 return 4 } const generatorObject = someNumberGenerator() generatorObject.next() // {value: 1, done: false} generatorObject.next() // {value: 2, done: false} generatorObject.next() // {value: 3, done: false} generatorObject.next() // {value: 4, done: true} generatorObject.next() // {value: undefined, done: true}

Yield nested generator function result

function* someNumberGenerator() { yield 2 yield 3 } function* otherNumberGenerator() { yield 1 yield* someNumberGenerator() yield 4 } const generatorObject = otherNumberGenerator() generatorObject.next() // {value: 1, done: false} generatorObject.next() // {value: 2, done: false} generatorObject.next() // {value: 3, done: false} generatorObject.next() // {value: 4, done: false} generatorObject.next() // {value: undefined, done: true}

Iterator object

let index = 1 const customIterator = { next() { if (index <= 4) { return { value: index++, done: false } } return { value: undefined, done: true } } }

Iterable class (Symbol.iterator) with generator function

function* someNumberGenerator() { yield 1 yield 2 yield 3 yield 4 } class SomeIterable { [Symbol.iterator]() { return someNumberGenerator() } } const someIterableInstance = new SomeIterable() [...someIterableInstance] // [1, 2, 3, 4]

Iterable class (Symbol.iterator) with iterator object.

let index = 1 class SomeIterable { [Symbol.iterator]() { return { next() { if (index <= 4) { return { value: index++, done: false } } return { value: undefined, done: true } } } } } const someIterableInstance = new SomeIterable() [...someIterableInstance] // [1, 2, 3, 4]

Async generator function

const asyncGenerator = async function* (): AsyncGenerator<number, void, unknown> { yield await new Promise((resolve) => setTimeout(() => resolve(1), 1000)) yield await new Promise((resolve) => setTimeout(() => resolve(2), 1000)) yield await new Promise((resolve) => setTimeout(() => resolve(3), 1000)) } ;(async () => { for await (const number of asyncGenerator()) { console.log(number) // 1, 2, 3 } })()

Class with async iterator.

class WithAsyncIterator { [Symbol.asyncIterator]() { return { i: 1, async next() { if (this.i <= 3) { return Promise.resolve({ value: this.i++, done: false }) } return Promise.resolve({ value: undefined, done: true }) } } } } const withAsyncIterator = new WithAsyncIterator() const runAsync = async () => { for await (const number of withAsyncIterator) { console.log(number) // 1,2,3 } } runAsync().catch(console.error)

Class with async iterator (as generator function)

class WithAsyncIterator { async *[Symbol.asyncIterator]() { yield await new Promise((resolve) => setTimeout(() => resolve(1), 1000)) yield await new Promise((resolve) => setTimeout(() => resolve(2), 1000)) yield await new Promise((resolve) => setTimeout(() => resolve(3), 1000)) } } const withAsyncIterator = new WithAsyncIterator() const runAsync = async () => { for await (const number of withAsyncIterator) { console.log(number) // 1,2,3 } } runAsync().catch(console.error)