frontend
Generator Functions in JavaScript
January 4, 2026
Generator Functions in JavaScript
Overview
Generator functions are special functions that can be paused and resumed. They use the yield keyword to pause execution and return values incrementally. Generators are particularly useful for handling asynchronous operations and creating iterators.
Basic Syntax
function* generatorFunction() {
yield 1;
yield 2;
yield 3;
}
const gen = generatorFunction();
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: 3, done: false }
console.log(gen.next()); // { value: undefined, done: true }
Generator Object Methods
function* numberGenerator(initialValue) {
yield initialValue;
console.log("Processing...");
yield initialValue + 10;
yield initialValue + 20;
}
const gen = numberGenerator(10);
// next() - resumes execution
console.log(gen.next()); // { value: 10, done: false }
console.log(gen.next()); // Processing... { value: 20, done: false }
// return() - terminates generator
console.log(gen.return(100)); // { value: 100, done: true }
// throw() - throws error into generator
const gen2 = numberGenerator(5);
gen2.next();
gen2.throw(new Error("Something went wrong"));
Iterating Generators
function* stringSequence() {
yield "First";
yield "Second";
yield "Third";
}
// Using for...of
for (let value of stringSequence()) {
console.log(value);
}
// First
// Second
// Third
// Using spread operator
const values = [...stringSequence()]; // ["First", "Second", "Third"]
Passing Values to Generators
function* generator() {
const x = yield 1;
const y = yield x + 2;
yield y + 3;
}
const gen = generator();
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next(10)); // { value: 12, done: false } (x = 10)
console.log(gen.next(20)); // { value: 23, done: false } (y = 20)
console.log(gen.next()); // { value: undefined, done: true }
Infinite Generators
function* infiniteCounter() {
let count = 0;
while (true) {
yield count++;
}
}
const counter = infiniteCounter();
console.log(counter.next().value); // 0
console.log(counter.next().value); // 1
console.log(counter.next().value); // 2
// ... continues indefinitely
Delegating to Another Generator
function* generator1() {
yield 1;
yield 2;
}
function* generator2() {
yield* generator1();
yield 3;
yield 4;
}
for (let value of generator2()) {
console.log(value);
}
// 1, 2, 3, 4
Use Case: Redux-Saga
Generators are commonly used in Redux-Saga for handling async operations:
function* fetchUser(action) {
try {
const user = yield call(api.fetchUser, action.userId);
yield put({ type: "USER_FETCH_SUCCEEDED", user });
} catch (e) {
yield put({ type: "USER_FETCH_FAILED", message: e.message });
}
}
Benefits
- Lazy Evaluation: Values are computed on-demand
- Memory Efficient: Only generates values as needed
- Async Control: Helps solve callback hell and inversion of control
- Iterable: Can be used with for...of loops and spread operator
Key Points
- Generators use
function*syntax andyieldkeyword - They return a generator object with
next(),return(), andthrow()methods - Useful for creating iterators and handling async operations
- Values are generated lazily, making them memory efficient