Javascript — pause and play.
Generators in Javascript.
As we all know in JS the program runs on a run-to-completion model, that is the processing can not pause and continue from where it was paused. So if you have a function like.
function printGretting() {
console.log('Good Morning,');
console.log('I am Saumya Dixit.');
console.log('What is your name ?');
}The function executes from top to bottom and the only way to exit any function is obviously when it ends, or when we return something before the function ends, or if it throws some error.
But with the introduction of ES6, we have something called a function generator, or just a generator.
For Example:
function* printGretting() {
console.log('invoked 1st time');
yield 1;
console.log('invoked 2nd time');
yield 2;
}But wait. What is this “yield [expression]” thing?
In a nutshell, we can command the function to execute till “yield [expression]” whenever we want and the function will return an indicator, that is an object having a key as “value” and its mapping with “expression”. It will be more clear with the example ahead, so don’t worry.
Remember that in JS if we don’t return anything from a function, by default the function returns undefined. In the case of a generator, it returns a Generator object which at first will be empty and no code will be executed.
Try out these two examples.
function printGretting() {
console.log('Good Morning,');
console.log('I am Saumya Dixit.');
console.log('What is your name ?');
}
const result = printGretting();
console.log(result);You will get:
Good Morning,
I am Saumya Dixit.
What is your name ?
undefinedNow try the same with the generator function:
function* printGretting() {
console.log('Good Morning,');
yield 1
console.log('I am Saumya Dixit.');
yield 2
console.log('What is your name ?');
}
const result = printGretting();
console.log(result);You will get:
Object [Generator] {}Note that: As this is an object it is iterable.
Get Saumyadixit07’s stories in your inbox
Join Medium for free to get updates from this writer.
To execute the code inside of a generator we can explicitly call the next method associated with it. It will run the code till the first yield keyword and return a generator object with the value property as 1, that is, it literally yielded/produced 1. (This is what I was talking about before when we first encountered the yield keyword)
So now make the following changes to your code to test it.
function* printGretting() {
console.log('Good Morning,');
yield 1
console.log('I am Saumya Dixit.');
yield 2
console.log('What is your name ?');
}
let result;
const printGrettingGen = printGretting();
result = printGrettingGen.next();
console.log(result);You will get the following output:
Good Morning,
{ value: 1, done: false }The yield statement returns 1 and pauses the generator at line 2.
When called again and again like so:
function* printGretting() {
console.log('Good Morning,');
yield 1
console.log('I am Saumya Dixit.');
yield 2
console.log('What is your name ?');
}
let result;
const printGrettingGen = printGretting();
result = printGrettingGen.next();
console.log(result);
result = printGrettingGen.next();
console.log(result);
result = printGrettingGen.next();
console.log(result);We get:
Good Morning,
{ value: 1, done: false }
I am Saumya Dixit.
{ value: 2, done: false }
What is your name ?
{ value: undefined, done: true }In the last message, the value is “undefined” as it is the end of the function, and no more yield statements are declared.
Alright cool. But wait, we have a Generator object and objects are iterable. So instead of calling the next, we can just loop over it, instead of calling the next function.
function* printGretting() {
console.log('Good Morning,');
yield 1;
console.log('I am Saumya Dixit.');
yield 2;
console.log('What is your name ?');
}
let result;
const printGrettingGen = printGretting();
for (let gen of printGrettingGen) {
console.log(gen)
}The output will be the following where 1 and 2 are the logs.
Good Morning,
1
I am Saumya Dixit.
2
What is your name ?Where can we use this?
- Iterating over large datasets: Generators can be used to iterate over large datasets where loading all data into memory at once is not feasible or efficient. They allow you to process data in chunks or on-demand, improving memory efficiency.
- Infinite sequences: Generators can be used to represent infinite sequences, such as a generator that yields Fibonacci numbers or prime numbers. Since generators can be lazily evaluated, you can consume values from these sequences without having to compute or store all values in memory.







