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)