I have been asked a few times and by different software developers about the possible use cases for Iterators/Generators (I/G). I have also noticed that some question if we really need them, and I do not blame them since in modern JavaScript there are a variety of ways to do the same thing most of the time.

In this article, I will share the two scenarios in which I have used I/G by using simpler examples, but that have a practical connotation and importance. This is not an explanation of what Iterators, Iterables and Generators are or how they work. There are good sources where that can be learned, for example, https://www.youtube.com/watch?v=ategZqxHkz4, or if you are the reading kind https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators, or my favorite explanation: Understanding ECMAScript 6: The Definitive Guide for JavaScript Developers by Nicholas C. Zakas. Do not feel disappointed or frustrated if you are not able to understand everything at first; very smart people including Douglas Crockford have admitted it is a complicated topic. So I decided to write this article to share how and why I have used them, just in case my personal experience can help someone.

First case scenario: Custom iterable sequences.

I need a collection of numbers that when iterated, it only gives me even numbers, and I want to be able to encapsulate the even number selection logic into my custom collection, so the code using it does not need to take care of that.

The EvenNumbers function takes an optional array that allows you to initialize the internal array that is used to maintain all the elements/items that are passed at first or inserted later. It returns an immutable object that has two properties, a function to add a new element, and a Symbol, that in this case is used to implement the default iterator for the custom collection.

Then we can use this function like this:

We created a custom collection initialized with an array that contains three elements, and later we add one more number to it. Then we iterate the collection and log each element to the browser console. If you give it a try, you should see only the numbers 2 and 10 getting printed out to the console. The beauty of this code is that the consumer of the EvenNumbers function knows what to expect, not worrying about even number selection logic because the involved logic was encapsulated by the EvenNumbers function itself. I know that you are probably thinking that code maintainability and reuse would beneficiate from this kind of approach, I am thinking the same. This is especially true when the iteration logic is way more complicated than simply selecting even numbers.

If you would rather have all those even numbers in a new array with only one line of code, you could just do this:

To verify, go ahead and print evenValues to the console.

Second case scenario: Writing asynchronous code that looks synchronous.

Asynchronous APIs are very common, take for example the readFile function from Node.js (https://nodejs.org/api/fs.html#fs_fs_readfile_path_options_callback). The idea is simple, after the input parameters the function takes another function as an argument, called callback, that is going to be executed when the result is ready or the action has been completed. In the case of readFile (and way more functions in Node.js), the callback function is executed by passing an error if something went wrong when reading the file from disk, or the content of the file if everything went fine.

We are going to use a function called fetchData that works in the same way that readFile does:

In order to simulate an asynchronous operation, that takes some time to complete, we have used setTimeout, and the lambda function passed to it will execute in approximately 1 second (technically it is not executed after about 1 second, it first gets placed into an asynchronous job queue and when it is its turn, it gets executed). This function tries to find a person based on the provided id, if it finds it, the callback gets called by passing the person to it. On the other hand, if the specified id does not belong to any person, an error is passed to the callback function. fetchData works very similar to readFile, and we could have implemented a real fetch by calling some API on the Internet to get data from, but I wanted to keep things simple and in-house.

The typical way to consume this function would be:

We have called fetchData and have passed the value 1 as the id, we have also passed the callback function as the second argument. In this way, if the person is found, we log its data to the console, if not, we throw the error.

I know you know that this asynchronous way of doing things, including the error handling logic, can get very messy and wild, leading to what is known as The Callback Hell. That’s the reason why better alternatives have appeared, like Promises and Observer/Observables. When using Promises you chain your method calls with then and catch, which does not make your code look like synchronous nor it lets you reason about it in that way. To overcome this, async/await made it to JavaScript, which under the hood uses Promises, but that is taken care of for you, so you can write asynchronous code that looks synchronous. Unfortunately, even when all major browsers support async/await, it is not supported everywhere; you could use Babel to make it work when it does not, but the generated code is huge, I saw an async function go from 5 lines to over 60 after being compiled by Babel.

All this leads to my second use case where I have used I/G, writing asynchronous code that looks synchronous, bare with me, please.

We have written a wrapper around fetchData, which is nothing more than a function that takes the id as a parameter and returns a function that accepts the callback and executes fetchData by passing both, the id and the callback.

Now is when I am really counting on you to be familiar with I/G, otherwise, it could be hard to understand the next function, which is commonly known as Asynchronous Task Runner.

There are libraries like Co that offer a similar function meant to run generators. It is not required to understand the run function to be able to use it; in C#, there is “some magic” under the hood that takes care of how async/await works, involving a state machine, and most of us (C# developers) have been successfully doing asynchronous programming in C# without knowing how this state machine works or why it works that way. But my advice to you will always be, research, study and learn so you can understand what you are using, even if it looks like a black box, that will always give you an edge and will make you feel happy.

Now all we have to do is:

Notice how that line of code containing yield and the next one using the result it produces look like synchronous programming, no callbacks, no then/catch chained, it just looks like C# async/await.

Combining this asynchronous task runner model with Promises will give you even more power and flexibility. If your requirements and environment allow you to, ECMAScript async/await will probably be better to control asynchronous flow; unless you need to tackle a way more complex scenario needing the flexibility and power of I/G.

Personally, I use RxJS whenever feasible, I love Reactive Programming, which I talk about in my articles: https://itnext.io/functional-reactive-programming-explained-in-a-simple-way-in-javascript-yes-in-a-simple-way-925b14cddf75 and https://itnext.io/i-would-love-to-see-you-do-it-better-and-cleaner-without-reactive-programming-545face12e1a, but I understand that paradigm is not appealing to everyone and it can get very complicated. So, as I always advise (because I learned like you, the hard way), choose the right tool for the job at hand, and at the end, feel happy and fulfilled with your solution.

I apologize for not explaining line by line the code in this article, it would have been outside of my goal, which was to share with those familiar with I/G (who wonder about practical use cases), where and why I have used them.

Happy coding!