Generators: Putting the sync back in asynchronous.

Jaaq Jorissen
3 min readFeb 21, 2016

Generators have been popping up left and right lately and I thought it was about time I understood what all of the fuzz was about. When I saw that co.js was one of the most popular packages on NPM, I realised I couldn’t run away from them any longer.

The first example you’re confronted with is the following:

After setting up the appropriate polyfills to deal with this exotic newcomer in Javascript, I copy/pasted it in my editor of choice and lo and behold, the word true was logged in my console! To be honest, it didn’t really explain to me what was happening so I decided to dig a bit deeper and figure out what exactly just took place.

Turns out, a generator is a function that will execute after you call .next() on an instance of it, and it will execute until it runs into ‘yield’, and it will then return whatever is behind the word yield. For a better explanation, I can suggest this great tutorial written by Alex Perry.

What is even better, the next time you call next() and send a value along with it, you overwrite this yield that was just returned to you. This has the wonderful implication that you can GET a variable from yield, do something with, and then SET it again by calling .next(value), which in turn will return the next variable.

One use case where this can be very useful is with Promises. You get a promise, resolve it, call .next(result) and get the next() Promise to resolve. So I decided to try exactly that.

The following gist shows a generator with 3 yields: Promises that do some asynchronous action. the function getURLPromise returns a Promise that fetches the body of the homepage of some tech giants.

After declaring my generator, I make an instance of it. I then pass it to my function resolvePromise that takes 2 arguments: the instance of the generator, and the result of the previous promise:

Note that I’m not using gen.next() but gen.next().value. This is because gen.next() does not actually return JUST the yields but an object with 2 properties: value and done. the property value contains the actual variable that was returned with yield and done is a boolean, indicating wether or not the generator has exhausted all of it’s yields.

After I get the promise from the generator, I resolve the promise using .then() and then recursively call resolvePromise again, with the instance of my generator as a first parameter, and the result as a second parameter.

Like I mentioned above, the Promise that was yielded after the first .next() call will now be overwritten by this .next(result) call, and my next Promise will be returned. This goes on until all yields (Promises in this case) have been exhausted.

When all yields have been exhausted, the generator will evaluate the last line, in this case an array with variables that kept track of our yields above. These should be filled up with results from the promises above.

Et voila: A bunch of asynchronous calls, that are neatly come together in a synchronous, predictable way — An array or values, in the order specified by us.

Now, this was a nice exercise to get an understanding of exactly how generators operate, but we can do the exact same thing with co.js with some added benefits:

What’s even better here is that co.js executes these promises in parallel, and adds delicious error catching to it!

I hope this tutorial gave you some understanding of what exactly co.js does and how generators work! I’ve uploaded the source code of this example to git if you want to check it out in detail.

I’d like to give a big thanks you to Martin for guiding me to the light of functional programming, and if you like this post feel free to follow me on twitter.

--

--