ES6 Generator Functions

Viswesh Subramanian
JavaScript Store
Published in
3 min readFeb 27, 2018

Generator functions are functions which have the ability to suspend execution for an indefinite period when it encounters a “yield”.

Let’s compare Generator functions to a humble function which we all know of –

function add() {
let x=1;
let y=2;
return x+y
}

When ‘add’ function executes, the execution is line by line — first, x is defined, y is defined and finally, x+y is returned. Can you suspend the execution? Well, you could perhaps use a promise but that’s not total suspension; when the promise resolves, the execution returns. With Generators, the code block which invoked the Generator can pause or resume execution.

function* panCakeInstructions() {
yield “Sift flour, baking powder, salt, and sugar”;
yield “Mix milk, egg, and butter”;
yield “Scoop batter on pan”;
yield “Serve hot when brown on both sides”;
}

Invoking the generator panCakeInstructions, an iterator is created and returned.

let instructions = panCakeInstructions();instructions.next().value //Sift flour, baking powder, salt, and sugar
instructions.next().value //Mix milk, egg, and butter
instructions.next().value //Scoop batter on pan
instructions.next().value //Serve hot when brown on both sides

Great! What is an iterator though?

ES6, in addition to introducing new native features and elegant syntaxes, it has also introduced ‘Protocols’. Protocols are conventions to standardize usage. By following protocols, we can all happily co-exist and play nice with each other.

The iterator protocol

An object is termed an iterator if it has next() interface which returns {value: <any>: done: Boolean}. The yielded value is returned along with a boolean flag ‘done’ to indicate whether the generator has yielded its last value.

The iterable protocol

An object is iterable if it implements “Symbol.iterator”.

Ok, Timeout! Let’s talk about Symbol.iterator for a second.

Symbol.iterator, according to mdn is “A zero arguments function that returns an object, conforming to the iterator protocol.” That’s a good explanation but let’s see it in action.

By invoking the Symbol.iterator function, we were able to iterate with the iterator object.

Back to our panCakeInstructions function — With Generators, we were able to pause the execution of the function, go step by step into instructions by yielding (returning) out results when next() was called by the caller.

Also, since the Generator function returns an iterator, we can also use for..of, which was specifically introduced for this purpose — to iterate over iterable objects.

for (const val of panCakeInstructions()){ 
console.log(val)
}

Before Async/Await, Generators was the way of life for folks who wanted to write async code in a synchronous way. Co, the Node.js generator based library turned out to be a huge hit among developers.

co(function *() {
let breeds = yield getBreeds();
let winner = yield getWinner(breeds);
return winner;
}).catch(function(err) {
console.error(err);
});

The wrapper function co takes in a Generator function, suspends it until the yielded promise is resolved and moves ahead. Check out co documentation for more examples.

In conclusion, Generators are great if you have a list of items to iterate over, suspend and resume processing based on necessity. For example, Infinite loading/scrolling — Once the initial set of items are loaded, you can suspend data load and resume based on user interaction.

References:

https://github.com/tj/co

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols

Originally published at javascriptstore.com on February 27, 2018.

--

--

Viswesh Subramanian
JavaScript Store

Full stack JS developer. Software generalist for the most part.