Intive Blog

ES6 Generators

We will get started by explaining the concept of “generators”, a new feature that incorporates ECMAScript to the language through its new standard, ES6. A generator is a function, being declared almost like a Javascript conventional function, except for a small change in its syntax. What is particular about this new feature is the ability of leaving and entering the generator at will.

Regarding the advantages, the use of generators leads us to clearer codes and can caution us against the well-known callback hell. Promises is a solution to this problem, although it does not allow us to get rid of the callback entirely. Consequently, we can celebrate: Generators are here to make us forget about callbacks!

Wrapping all up, we can pause the generator execution and allow the code to keep on running outside. Later, we “tell” it to run again from where we had paused it.

In brief: we can suspend it and be able to get into this generating function again at will.

To understand this process better, let’ see a bit of code.

 

Syntax and performance

As regards the syntax, among the news we can point out the incorporation of new words reserved for the language, both to create a generating function and to set its suspension. Let’ see how it is defined:

The * (asterisk) can be placed either at the end of the keyword function or before the name of the generating function. By convention, you write function *. A generator can be in suspended or closed mode.

  • Within the generating function, keyword yield will be used. With this new reserved word, we “tell” the function: “run this/these line/s of code and pause the generator”. This means that yield suspends the execution of the generator to resume it later.
  • Generators accept parameters anytime. (Both in the definition of the generator and in the invocation of the method next, gen.next(param)):
In this example we are creating a generating function that has two pauses. It is necessary to obtain an instance of the generator, hence, the variable gen calls generator Function, which will return a suspended Generator object. Once the method .next() is called, the call to the function is frozen and executed until the next yield expression arrives. The first call to .next() that we run gives us what follows:
The property value is the result of executing the operations from the yield. The property done is a way that the generator has to indicate when it finishes executing all the sentences.

The next call to the method .next() will print the result of the previous sentence and return an object indicating this operation status:

Now, the last call to the generator will return an object with the field value as undefined, since no value is returned and done with the value true, indicating that the generator has finished executing all the sentences inside it. From then on, every time we call the method .next() we will get the same object:

  •  As we saw, we invoked the method .next() three times despite having two yield. We should bear in mind that the amount of calls to the method .next() is the amount of expressions yield on our generator plus one, that is to say, we perform yield+1 invocations to .next().

Finally, if we check the instance of the generator we had created (the variable gen), we will see that the generator status is closed, that is, all the generator sentences have been executed. The result would be:

 

An interesting use of generators

A practical use for generators is to avoid callbacks (as it was mentioned) once we obtain the result from a Promise. That means, we will have a more simple code and we will significantly reduce the calls to the method .then().

In this case, we will use a library called “co” for the example, to which a generator will be passed and it will eventually give us a Promise when the complete execution of the generator is finished. Besides, we will compare it with what would happen if we only used Promises:

As we can see, the code is much clearer. Co allows us to avoid manually the call to the method .next() of the generator and in turn, it is responsible for executing the next expression yield after the previous has been completed. Finally, co will return a Promise.

 

Conclusion

To sum things up, eventually, a generator is a function that can be suspended and executed again from the last point. A new reserved word yield is added, and we are given a way to declare generators with the expression function*.

We can say generators are a step forward for the Promises, since they provide us with a clearer and cleaner way to generate asynchronous code compared to how we had been going about it. Topics such as Iterators in generators will be dealt with in future articles.

Currently, there are some browsers that do not support generators. Babel, among others, will give us the solution for those who feel like experimenting or applying these new features to their code.

Looking into the future of javascript, a new feature to the language called async/await will arrive, based on a similar concept to the one of generators, capable of suspending and executing again from the last point. The syntax put forward with async/await will simplify the code we normally generate even further.

For those willing to go deeper as regards generators, we suggest visiting these links:

Mariano Furriel

He’s been a developer in the company since March 2016 . He is studying the Computer Engineering degree at UADE. He is always attentive to read and learn about new technologies to improve the application designs.

Add comment