Introduction
A generator function is a special type of JavaScript function that can pause and resume its execution. Unlike a regular function, which runs from beginning to end in one execution, a generator function can return multiple values over time using the yield keyword.
Generator functions were introduced in ES6 (ECMAScript 2015) to provide a simple way to create custom iterators and generate values on demand.
When a generator function is called, it does not execute immediately. Instead, it returns a Generator object. The function begins executing only when the generator’s next() method is called.
In Node.js, generator functions are useful for creating sequences, processing large datasets, implementing lazy evaluation, and generating test data efficiently.
Although Async/Await has largely replaced generators for asynchronous programming, generator functions remain an important JavaScript feature and are still useful in several scenarios.
In this tutorial, you’ll learn how generator functions work and how to use them effectively.
What are Generator Functions?
A generator function is declared using the function* syntax.
Instead of using only the return statement, generator functions typically use one or more yield statements to return values one at a time.
Each time the next() method is called, execution continues from the previous yield statement.
Why Use Generator Functions?
Generator functions help developers:
Generate values on demand.
Pause and resume execution.
Create custom iterators.
Process large datasets efficiently.
Reduce memory usage.
Implement lazy evaluation.
Generate infinite sequences.
Syntax
function* generatorName() {
yield value1;
yield value2;
}
Example 1: Basic Generator Function
function* numbers() {
yield 1;
yield 2;
yield 3;
}
const generator =
numbers();
console.log(
generator.next()
);
console.log(
generator.next()
);
console.log(
generator.next()
);
Sample Output
{ value: 1, done: false }
{ value: 2, done: false }
{ value: 3, done: false }
Example 2: Generator Completion
function* colors() {
yield "Red";
yield "Green";
}
const generator =
colors();
console.log(
generator.next()
);
console.log(
generator.next()
);
console.log(
generator.next()
);
Sample Output
{ value: 'Red', done: false }
{ value: 'Green', done: false }
{ value: undefined, done: true }
Example 3: Generator with Loop
function* countNumbers() {
for (
let i = 1;
i <= 5;
i++
) {
yield i;
}
}
for (
const number
of countNumbers()
) {
console.log(number);
}
Sample Output
1
2
3
4
5
Example 4: Returning a Value
function* demo() {
yield "First";
return "Finished";
}
const generator =
demo();
console.log(
generator.next()
);
console.log(
generator.next()
);
Sample Output
{ value: 'First', done: false }
{ value: 'Finished', done: true }
Example 5: Infinite Generator
function* generateIds() {
let id = 1;
while (true) {
yield id++;
}
}
const generator =
generateIds();
console.log(
generator.next().value
);
console.log(
generator.next().value
);
console.log(
generator.next().value
);
Sample Output
1
2
3
Automation Testing Examples
Generator functions can simplify repetitive automation tasks by generating values only when needed.
Playwright Example
Generate browser names.
function* browsers() {
yield "Chrome";
yield "Firefox";
yield "Edge";
}
for (
const browser
of browsers()
) {
console.log(browser);
}
Sample Output
Chrome
Firefox
Edge
Selenium Example
Generate test environments.
function* environments() {
yield "QA";
yield "Staging";
yield "Production";
}
const generator =
environments();
console.log(
generator.next().value
);
console.log(
generator.next().value
);
Sample Output
QA
Staging
Cypress Example
Generate user roles.
function* roles() {
yield "Admin";
yield "Manager";
yield "User";
}
for (
const role
of roles()
) {
console.log(role);
}
Sample Output
Admin
Manager
User
API Testing Example
Generate API versions.
function* apiVersions() {
yield "v1";
yield "v2";
yield "v3";
}
const generator =
apiVersions();
console.log(
generator.next().value
);
Sample Output
v1
Data-Driven Testing Example
Generate test case IDs.
function* testCases() {
yield "TC001";
yield "TC002";
yield "TC003";
}
for (
const testCase
of testCases()
) {
console.log(testCase);
}
Sample Output
TC001
TC002
TC003
Common Uses of Generator Functions
Generator functions are commonly used for:
Custom iterators.
Lazy evaluation.
Infinite sequences.
Test data generation.
Processing large datasets.
Streaming data.
Pagination.
Workflow control.
Simulation programs.
Educational demonstrations.
Generator Functions vs Regular Functions
| Feature | Generator Function | Regular Function |
|---|---|---|
| Declaration | function* | function |
| Returns | Generator object | Function result |
| Execution | Pauses and resumes | Runs completely |
Uses yield | Yes | No |
| Multiple Values | Yes | No |
| Execution Control | next() | Automatic |
Common Mistakes
Forgetting function*
A generator must be declared using function*.
Expecting Immediate Execution
Calling a generator function returns a Generator object. The function body does not execute until next() is called.
Forgetting to Call next()
Without calling next(), no yield statements are executed.
Best Practices
Use generator functions for sequential value generation.
Keep generator logic simple.
Use meaningful generator names.
Use
for...ofwhen iterating through all generated values.Use generators for large or infinite sequences.
Avoid generators for simple functions that do not require pausing.
Prefer Async/Await for asynchronous programming.
Conclusion
Generator functions provide a flexible way to pause and resume execution while generating values one at a time. They are ideal for creating iterators, producing sequences, and processing large datasets efficiently without loading everything into memory.
For automation engineers, generator functions can simplify the generation of test data, user roles, browser configurations, API versions, and unique identifiers. Although Async/Await has become the preferred approach for asynchronous programming, understanding generator functions strengthens your knowledge of JavaScript’s advanced features and execution model.
Frequently Asked Questions (FAQs)
What is a generator function?
A generator function is a special function declared using function* that can pause and resume execution using the yield keyword.
What does a generator function return?
It returns a Generator object, not the final result directly.
How do I execute a generator?
Call the generator’s next() method to start and continue execution.
What is the difference between yield and return?
yield pauses execution and allows it to continue later, while return ends the function permanently.
Why are generator functions useful in automation testing?
They help generate test data, IDs, environments, user roles, and other sequential values efficiently without storing everything in memory.
Key Takeaways
Generator functions are declared using
function*.They return a Generator object.
Execution begins only when
next()is called.yieldpauses execution and returns a value.Generator functions can produce multiple values.
They are useful for lazy evaluation and custom iterators.
for...ofworks naturally with generators.Generator functions are memory-efficient for large or infinite sequences.
Async/Await is generally preferred for asynchronous programming, while generators are ideal for controlled value generation.
Understanding generator functions is an important part of mastering advanced JavaScript.
