ES6 generators. What’s the big deal?

The generators are not a new concept. They appeared in many languages (C++, Java, PHP, Haskell, Ruby, Python … to name a few), where they are implemented differently but allows you to achieve one common pattern. Now they finally appeared in the JavaScript. I’m writing this article because I observe lot of programmers that does not give this construct proper attention. Attention that it deserves.

What are generators?

Let’s start from the beginning. Generator is a function that allows to represent values sequence. Basically it behaves exactly like an iterator, pausing it’s execution between calls.

A generator looks like a function but behaves like an iterator.

The example implementation of an generator for Fibonacci sequence could look like this:

function* fibonacci() {
let current = 0;
let next = 1;
    for(;;) {
yield current;
[current, next] = [next, current + next];
}
}

As you can see the new concept is the asterisk and yield statement. I don’t want to get into the syntax details so for this part I’d recommend to read excellent post on the David’s blog.

How do I really benefit?

So you red all those posts about generators introduction. You know the syntax and can write some simple (or even more complex) generator. But there is one big question getting back to your mind: Why the hell should I use those things? The answer is pretty simple and get’s back to the constant mantra of every programmer: keep your code simple and manageable. Below I will present you some of the scenarios in which generators perfectly fit in.

Endless data handling

This is quite common these days. Rich web app with fancy endless scroll on the news section. This thing requires data fetching on some mouse/position trigger. Using generator you can make it really straightforward.

function* getArticles() {
let offset = 0;
let articlesService = new ArticlesService();

for(;;) {
// Probably a Promise
yield articlesService.get(offset++);
}
}

This way you can create your generator and hit next() on it every time your precious reader gets near the bottom of the page. You could do this using regular tools that JavaScript dev had up to ES6 but using generator you will encapsulate offset tracking, service generation (only once) and fetching logic in single place.

Making async easy

Due to generators ability of holding function execution, you can use it to handle asynchronous tasks exactly as you did with synchronous code. This requires some extra toolkit (at least until async/await functions in ES7). Below is example with the Q library.

Q.spawn(function* () {
// The computation tasks are async
// time consuming tasks
let c1 = yield async1();
let c2 = yield async2();
    makeSideEffect(c1 + c2);
});

Again, readability of such code is way better than infamous callback hell we needed to deal with some time ago.

Dividing consumers and producers

Generators can reduce complexity in very complex loops we encounter from time to time. With them on board you can divide the logic of creating data from the logic responsible for data consumption.

Memory management

Imagine you need to get and process 1000 huge objects. After processing those crazy object reduces to the some small info for the customer. Generators allows you to handle this task one by one and preserve ability to handle your data as array — just like before.

Just use it

Generators are like any other tool you have in your everyday coding arsenal. When you’ll get used to it and adopt new syntax, they will get more and more handy each day. The few examples I provided above is just a obvious starter for exploring this road.