Understanding JavaScript Generators


If you're a JavaScript developer, you may have heard about generators—a powerful feature introduced in ES6. They might seem confusing at first, but once you get the hang of them, they can make your code more flexible and memory-efficient.
Let’s break it down step by step.
🧠 What is a Generator ?
A generator is a special kind of function that can pause and resume its execution.
Unlike normal functions that run from top to bottom in one go, generators return values one at a time, on demand.
You create a generator by using the function*
syntax and yield
keyword.
📌 Syntax
function* generatorFunction() {
yield 'First';
yield 'Second';
yield 'Third';
}
Calling generatorFunction()
does not run it—it returns an iterator object.
▶️ Running a Generator
const gen = generatorFunction();
console.log(gen.next()); // { value: 'First', done: false }
console.log(gen.next()); // { value: 'Second', done: false }
console.log(gen.next()); // { value: 'Third', done: false }
console.log(gen.next()); // { value: undefined, done: true }
Each next()
call resumes the generator until the next yield
.
✅ When to Use Generators
Generators shine when:
You need to pause/resume a task.
You're generating values lazily (like infinite data streams).
You're managing complex asynchronous flows (e.g., older Redux-Saga).
🛠 Practical Example: Generating IDs
Let’s build a simple ID generator
that gives unique IDs each time it's called.
function* idGenerator() {
let id = 1;
while (true) {
yield id++;
}
}
const getId = idGenerator();
console.log(getId.next().value); // 1
console.log(getId.next().value); // 2
console.log(getId.next().value); // 3
This is great when you want controlled or custom auto-increment logic.
🔁 Generator with for...of Loop
function* fruitGenerator() {
yield '🍎 Apple';
yield '🍌 Banana';
yield '🍇 Grape';
}
for (const fruit of fruitGenerator()) {
console.log(fruit);
}
Output:
🍎 Apple
🍌 Banana
🍇 Grape
The for...of
loop works seamlessly with generators!
⏱ Generator for Delayed Execution
Let’s simulate a step-by-step animation or process:
function* steps() {
console.log('Step 1');
yield;
console.log('Step 2');
yield;
console.log('Step 3');
}
const flow = steps();
flow.next(); // Step 1
flow.next(); // Step 2
flow.next(); // Step 3
This pattern is super useful in tutorials, onboarding steps, or guided flows.
🤯 Bonus: Passing Data into Generator
You can also send values into a generator:
function* multiplier() {
const num = yield 'Give me a number';
console.log(`Result: ${num * 10}`);
}
const gen = multiplier();
console.log(gen.next().value); // "Give me a number"
gen.next(5); // Logs "Result: 50"
This allows for two-way communication between your code and the generator.
📚 Summary
Concept | Description |
function* | Declares a generator function |
yield | Pauses the function and returns a value |
next() | Resumes the function from where it left off |
done | Boolean indicating if the generator is finished |
🧵 Real-Life Use Cases
Controlled sequences (IDs, pagination)
Lazy data structures (tree traversal, infinite scroll)
Redux Saga (asynchronous state management)
Animations or onboarding flows
Custom iterators for objects
🧩 Final Thought
Generators can look weird at first, but once you try them in real-world scenarios, they start to make a lot of sense. They help you write more readable, more controlled, and lazy-executing code.
Give them a try in your next small tool or app feature—you might be surprised how useful they are.
Subscribe to my newsletter
Read articles from Shaik Lubaba directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
