ES6 Generators

Generator (or Generator function) is the new concept introduced in ES6. It provides you a new way of working with iterators and functions.

ES6 generator is a different kind of function that may be paused in the middle either one or many times and can be resumed later. When the standard function is called, the control rests with the called function until it returns, but the generator in ES6 allows the caller function to control the execution of a called function.

ES6 Generators

A generator is somewhere identical to the regular function except that:

  • When the generator gets called, it doesn't run its code. Instead, it returns a special object which is called as 'Generator Object' for managing the execution.
  • The generator function can return (or yield) the control back to the caller at any point.
  • Unlike the regular function, the generator can return (or yield) the multiple values, one after another, on the requirement.
Syntax

The syntax of the generator function is almost identical to regular function. The only real difference is that the generator function is denoted by suffixing the function keyword with an asterisk (*).

In the following syntax, we are showing you some of the valid ways of defining the generator function:

function* mygenfun()	// Valid
{
yield 1;
yield 2;
...
...
}

function *mygenfun()	// Valid
{
yield 1;
yield 2;
...
...
}

function*mygenfun()	// Valid
{
yield 1;
yield 2;
...
...
}
Example
snippet
function* gen()
{
yield 100;
yield;
yield 200;
}
// Calling the Generator Function
var mygen = gen();
console.log(mygen.next().value);
console.log(mygen.next().value);
console.log(mygen.next().value);
Output
100 undefined 200

yield statement

The yield statement suspends the function execution and sends a value back to the caller. It retains enough state to enable function to resume where it is left off. When it gets resumed, the function continues the execution immediately after the last yield run. It can produce a sequence of values.

next() method

In the above example, we have used the next() method, which is the main method of the generator. When you call the next() method along with an argument, it will resume the execution of the generator function, replacing the yielded expression where the execution was paused with the argument from the next() method.

The result of the next() method is always an object having two properties:

  • value: It is the yielded value.
  • done: It is a Boolean value which gives true if the function code has finished. Otherwise, it gives false.

For instance, here, we are creating a generator function and gets its yielded value.

Example
snippet
function* show() {
yield 100;
}

var gen = show();	//here 'gen' is a generator object
console.log(gen.next()); // { value: 100, done: false }
Output
{ value: 100, done: false }

Generator object

The generator functions return generator objects. A generator object is an instance of the generator function, and it conforms to both the iterable and iterator interfaces.

The generator objects can be used either by calling the next() method or by using the generator object within a loop. The generator object is an iterator; that's why you can use it in for…of loops or in other functions accepting an iterable.

In the above next() method example, the variable gen is the generator object.

Return Statement in a Generator

Return is used to send a specified value back to its caller. It is used to end the function call execution and returns the result to the caller. Within a function, the statements defined after the return statements are not executed. That's why the return statement should be the last statement of the function.

Let us try to understand the return statement in a generator by using an example:

Example
snippet
function* myGen()  {
yield 'First yield statement';
yield 'Second yield statement';
return 'Return statement';
yield 'Second yield statement';
}
let genobj = myGen();

console.log(genobj.next());    //returns {value: 'First yield statement', done: false}

console.log(genobj.next());   //returns {value: 'Second yield statement', done: false}

console.log(genobj.next());  //returns {value: 'Return statement', done: true}

console.log(genobj.next());	//returns {value: undefined, done: true}
Output
{ value: 'First yield statement', done: false } { value: 'Second yield statement', done: false } { value: 'Return statement', done: true } { value: undefined, done: true }

In the above example, we have defined a generator function myGen() in which we have defined four statements, including three yield statements and a return statement. Whenever we call the next() method, the function resumes until it hits the next yield statement.

You can notice how the first next() method returns 'First yield statement .' When we call the next() method a second time, it resumes the execution and returns 'Second yield statement'. After calling the next() method again, the function finds no more yield statement and returns the 'Return statement.' But when we call the next() method fourth time, it will not consider the yield statement and returns undefined because it is written after the return statement.

You can see in the output of the above example that the next() method is not considering any statement after the return statement.

Generator function with for...of loop

Using for...of loop with generator function reduces the line of code. You can see the illustration for the same in the following example.

Example
snippet
"use strict" 
function* vowels() { 
   // here the asterisk marks this as a generator 
   yield 'A'; 
   yield 'E'; 
   yield 'I'; 
   yield 'O'; 
   yield 'U'; 
} 
for(let alpha of vowels()) { 
   console.log(alpha); 
}
Output
A E I O U
Note
Generator functions cannot be represented by using the arrow functions.
Related Tutorial
Follow Us
https://www.facebook.com/Rookie-Nerd-638990322793530 https://twitter.com/RookieNerdTutor https://plus.google.com/b/117136517396468545840 #
Contents +