17.6 C
Jaipur
Thursday, January 20, 2022

Generators in JavaScript | Explained with Examples

Must read

Generators are functions that are used to get multiple values at various times. Generators are a bit complex to understand so we are going to define what generators are in simple words and then go into detail about generators and their working.

JavaScript often comes up with solutions for various problems especially with the arrival of the ES6 version of JavaScript. One of the key features that were introduced in ES6 was Generators, Generators in JavaScript are used with iterators to create a flow of data or a stream of data. Generators help us avoid callback function issues.

What actually are generators

In simple words, Generators are special functions; unlike normal functions that only have one return statement, Generators return multiple values but at different times.

To be more descriptive, generators are functions that return value mid-way through the function and then stop executing after saving the state, this step of returning a value, saving state, and halting execution is called yielding a value and pausing.

During this pause, the program can work on some other functionality, and then when we are required, the generator is asked to return the next value, but rather than restarting the whole function, the generator runs from the point where it stopped and yields the next value. Thus, creating a constant stream of data. That is why these functions are called “Generators” as they are used to generate the stream of data.

We can look at the following working diagrams to better understand the difference between normal and generator functions:

And generator function work like this:

How to define a Generator function?

Since generator functions are special functions that is why we use a special keyword while defining them that is “function*” – asterisk after the function keyword. The syntax is as:

function* functionName (params) {

// body of the function

yield value;

}

Note:

  • Function*: keyword for defining generator functions
  • functionName: The identifier for this function
  • Params: Optional parameters that you want to use
  • Yield: Returns value and halts the execution of the function

Return value: Object [ Generator ] – A generator Object OR undefined if generator is empty

We are now familiar with what a generator function is, but we are still not familiar with its return type that is the “Generator Object”.

What is a generator object?

When a generator function is created it returns an object that we must initialize in some variable, this variable is then known as the Generator Object. This generator object is used to get the next value from the function.

Syntax of initializing a generator object

variable = generatorFunctionName( arguments );

After you have created the generator object you can use the function “object.next()”

The object.next() returns a JSON object with two properties, one is the “value” and the other is the “done” property.

Getting Values from a generator function

Let’s create a simple generator function that will return us a new value every time it is called, with the following lines of code:

function* generator() {

yield 1;

yield “FOUND”;

yield 3;

}

Now that we have a generator we need to initialize it with a generator object, we do that with the following statement:

const genObject = generator();

Now we have the generator object as well. All we have to do now is to call the next() function of the generator object and print the JSON object with the console.log() function.

console.log(genObject.next());

console.log(genObject.next());

console.log(genObject.next());

The complete code snippet looks like this:

function* generator() {

yield 1;

yield “FOUND”;

yield 3;

}

const genObject = generator();

console.log(genObject.next());

console.log(genObject.next());

console.log(genObject.next());

We get the following output:

As you can see, we have printed 3 different JSON objects with 3 different calls to the same generator function. But, sometimes we want to use the value, not the JSON object. We can do that by accessing the value property of the JSON object with the following line of code:

console.log(genObject.next().value);

console.log(genObject.next().value);

console.log(genObject.next().value);

With these lines, we get the following output:

As you can see, the object.next().value returns us a value which we can even pass onto some other function.

Working of generator function in simultaneous code execution

For this tutorial, let’s create a simple generator function that will yield numbers from 1 to 5 and after every number that we fetch from the generator, our program will alert us that it is doing some calculations on that number and has left the generator function.

The first step is to create a generator function that will yield 5 different numbers on 5 different calls with the following lines of code:

function* generator() {

console.log(“Generator Function Initialized”);

for (let i = 1; i <= 5; i++) {

console.log(“Inside Generator for new yield”);

yield i;

}

}

As you can see, we have created a loop that will return 1 new integer on every generator yield call and prompt us whenever the program is inside the generator function.

Now, we need to initialize this generator function with the generator object with the following line of code.

const genObject = generator();

Now, we need a function that will do some work on the yielded values, create the function using the following lines:

function tablePrinter(num) {

console.log(`Currently Printing the Table of : ` + num);

}

We have a generator function, a generator object, and a function that will work on some values that are passed inside it. Now, all we need is an iterator that will iterate through the generator object and pass the values to the function. We do that by using the following lines of code:

yieldedValue = genObject.next().value;

while (yieldedValue) {

tablePrinter(yieldedValue);

yieldedValue = genObject.next().value;

}

What this code will do is that it will take the next value from the generator and store it inside a variable. Then in the while loop, it will check if the variable is undefined or not, and if it is not undefined then it will pass this value to the function “tablePrinter” and move on to the next value.

The complete code snippet is as:

function* generator() {

console.log(“Generator Function Initialized”);

for (let i = 1; i <= 5; i++) {

console.log(“Inside Generator for new yield”);

yield i;

}

}

const genObject = generator();

function tablePrinter(num) {

console.log(`Currently Printing the Table of : ` + num);

}

yieldedValue = genObject.next().value;

while (yieldedValue) {

tablePrinter(yieldedValue);

yieldedValue = genObject.next().value;

}

The output of the following code is:

As you can see, the program goes inside the generator function and yields a new value, saves states, pauses the execution of the function, goes inside the “tablePrinter” function, and performs execution there. Once done it goes back inside the generator function for a new yield. This whole process is repeated until the generator keeps producing new yields. Thus, making it a Stream of data.

That’s it for Generators in JavaScript.

Conclusion

Generators are special functions that can halt their execution mid-way to yield a value, save their state and allow the program to perform other tasks. When needed the generator function “resumes” their execution from the state that they paused in. Generators are used to generate a constant stream of data. They are used in collaboration with promises and iterators to create an infinite stream of data and to avoid callback function issues.

Source link

- Advertisement -

More articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisement -

Latest article