JavaScript Generators and Iterators
Generator functions let you define lazy sequences and write pauseable functions. They are the foundation of async/await and enable memory-efficient data processing patterns.
// Generator function: uses function* and yield
function* count(start = 0, step = 1) {
let n = start;
while (true) {
yield n;
n += step;
}
}
const counter = count(1, 2); // 1, 3, 5, 7, ...
console.log(counter.next()); // { value: 1, done: false }
console.log(counter.next()); // { value: 3, done: false }
// for...of automatically calls next() until done: true
function* range(start, end) {
for (let i = start; i <= end; i++) yield i;
}
console.log([...range(1, 5)]); // [1,2,3,4,5]
yield* — Delegate to Another Generator
function* nums() { yield 1; yield 2; }
function* letters(){ yield 'a'; yield 'b'; }
function* combined() {
yield* nums();
yield* letters();
yield 'done';
}
console.log([...combined()]); // [1, 2, 'a', 'b', 'done']
Two-Way Communication
function* dialogue() {
const name = yield 'What is your name?'; // sends question, receives answer
const age = yield `Hello ${name}! How old are you?`;
yield `${name} is ${age} years old.`;
}
const gen = dialogue();
console.log(gen.next().value); // 'What is your name?'
console.log(gen.next('Rahul').value); // 'Hello Rahul! How old are you?'
console.log(gen.next(25).value); // 'Rahul is 25 years old.'
Custom Iterators
class Range {
constructor(start, end) {
this.start = start;
this.end = end;
}
[Symbol.iterator]() {
let current = this.start;
const end = this.end;
return {
next() {
return current <= end
? { value: current++, done: false }
: { done: true };
}
};
}
}
const r = new Range(1, 5);
console.log([...r]); // [1,2,3,4,5]
for (const n of r) console.log(n); // 1 2 3 4 5
const [first, ...rest] = r; // destructuring works!
Q: How does async/await relate to generators?
async/await was originally implemented using generators in transpilers like Babel. An async function is essentially a generator that automatically resumes when Promises resolve. The await keyword corresponds to yield, and the runtime acts as the controller that calls .next() when the Promise resolves.
Comments (0)
No comments yet. Be the first!
Leave a Comment