Hold Up - What Are JavaScript Generators?

This article was originally posted on my blog

We learned JavaScript knowing that functions execute from top-to-bottom, just like we read English from right-to-left. That all changed when ES6 was released in June of 2016, bringing with it the ability to pause functions in the middle of execution.

How does this work? Generators! Also known as Generator Functions.

A generator function can be paused at any given point and continue where it left off when told to do so. Pretty crazy, right?

Let's take a look at a basic example.

Creating a JavaScript Generator Function

Generator functions in JavaScript are created much like any other function, except for one difference in syntax. Can you spot it?

function* tacoIngredients() {
  yield 'Shell';
  yield 'Meat';
  yield 'Lettuce';
  yield 'Cheese';
}

The difference is in the function definition itself - generator functions are written using the function* syntax.

The JavaScript Generator Yield Keyword

You probably noticed the yield keyword in the example above. When a generator function is called, it executes until it encounters a yield expression. At this point, the generator function pauses, returns the value defined after the yield keyword, and waits to continue execution until the function is called again.

Returning Values from JavaScript Generator Functions

Here's another difference between Generators and regular functions in JavaScript: generator functions return its value in a wrapped object. Why? Because technically, Generators conform to the Iterator protocol (think Maps and Observables), which means the wrapped object looks like this:

{
  value, // the next value you want to get from the generator function
    done; // a flag informing you if this is the last value in the sequence
}

If we wanted to get the data in the tacoIngredients function defined in the example above, it would look something like this:

function* tacoIngredients() {
  yield 'Shell';
  yield 'Meat';
  yield 'Lettuce';
  yield 'Cheese';
}

const taco = tacoIngredients();

console.log(taco.next()); // { value: 'Shell', done: false }

Each time we call the next() method, an object is returned in the shape mentioned prior. To get the data, simply access the value property. Because the done property has a value of false, we know there is more data to be retrieved and we can call the generator again.

function* tacoIngredients() {
  yield 'Shell';
  yield 'Meat';
  yield 'Lettuce';
  yield 'Cheese';
}

const taco = tacoIngredients();

console.log(taco.next()); // { value: 'Shell', done: false }
console.log(taco.next()); // { value: 'Meat', done: false }
console.log(taco.next()); // { value: 'Lettuce', done: false }
console.log(taco.next()); // { value: 'Cheese', done: false }
console.log(taco.next()); // { done: true }

If we call next() after the generator has encountered its last yield keyword, it returns an object with a single property - and it's probably what you're expecting - done is set to true!

Wrapping Up

JavaScript Generator Functions are really cool - and I hope this article helped you understand how to use them in your own projects!

Want a real-world example? Here's a CodePen demo I made that calculates the Fibonacci sequence using JavaScript Generator Functions!

Resources

Thanks for reading! If you enjoyed this article, consider sharing it on Twitter and signing up for my developer newsletter so you don't miss out on my future content!

Cover photo by Chris Dickens / Unsplash

28