Javascript: Generator functions

Image for post
Image for post

What is a generator function?

How does a generator function work?

function normalFunction() {
console.log("I am executing");
var data = 3;
console.log("I am still executing", data);
data = 4;
console.log("I am done executing", data);
}

Two things to be noted here:

  • The control goes out of the function only after it is fully executed.
  • The function execution starts from the very first line, regardless of where it is called from.

Generator function:

  • Generator function can be exited before it fully completes execution.
  • Generator function execution can be resumed from any line, not necessarily the first line.
  • Generator function returns an iterator object. The object can be used to execute the function call multiple times.
  • Generator function returns a sequence of values instead of a single value

How to create and use a generator function

  1. yield: The place where yield is used is the place where the function pauses the execution. This keyword can also be used to return any data.
  2. next: The next acts much like a callback function. When it is called, the generator function resumes its execution.

Let’s look at an example:

function * generatorFunc() {
var value = "value";
console.log("I am starting my execution ", value);
yield "value1";

console.log("I am resuming execution after first pause ", value);
yield "value2";

console.log("I am resuming execution after second pause ", value);
}

const generator = generatorFunction();
console.log(generator.next().value); // I am starting my execution value
// vaule1
console.log(generator.next().value); // I am resuming execution after first pause value
// value2
console.log(generator.next().value); // I am resuming execution after second pause value
// undefined
  1. The generator function is like any normal function, with the yield keyword where the function needs to be paused.
  2. The first call to the generator function doesn’t start the execution of the code inside the function, however, it instantiates the function returns a generator object.
  3. The subsequent calls to the generator function is made by calling the next() function on the generatorObject that was returned from the function.
  4. The value returned from the yield comes back to the main control.
  5. The variable values within the generator function is preserved throughout the execution.

Uses of generators

Using generators as iterators:

function * loopme() {
yield "One";
yield "Two";
yield "Three";
}

for(const val of loopme()){
console.log(val);
}

// One
// Two
// Three

A generator function inside a for--of loop can be iterated. This way, the return values can be used much like any other for loop implementations.

Async functions:

function foo() {
return new Promise((resolve, reject) => {resolve(3)});
}

foo()
.then((val) => console.log(val))
.catch((err) => console.log(err));

The same can be implemented using the generator function as follows:

function foo() {
return new Promise((resolve, reject) => {resolve(3)});
}

function *asyncFunc() {
var data = yield foo();
console.log(data);
}

This looks similar to async-await implementation. Instead of using async, we are using yield. The asyncFunc can be now called like any normal promise using next().

var asyncFuncObj = asyncFunc();
var promiseObj = asyncFuncObj.next().value;

promsieObj
.then((val) => console.log(val))
.catch((err) => console.log(err));

When the asyncFunc is called, the object returned is similar to the "pending state" of a promise.

Image for post
Image for post

Note that the function is in a suspended state.

Advantages of generator functions

Lazy evaluation:

function * lazy() {
var x = 2;
var y = yield x;
return y + x;
}

var lazyObj = lazy();
lazyObj.next()
console.log('sum: ', lazyObj.next(3).value);

Here, the value of y is computed only when the generator function is executed for the second time. Until then, y is not evaluated. Since the values are computed on the fly, the generator functions are memory-efficient. Only the required values are stored in memory.

It is important to note that, once the generator function has completed its execution, it cannot be iterated using the same object again. A new object must be created to iterate through the function again.

Written by

CODER | BLOGGER | ARTIST | GHOST

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store