I recently added a new chapter to my Asyc JavaScript book, you can check it out at asyncjsbook.com. Below is an excerpt from the book.

Generators

Generators are special functions that generate values when you need them to. When you call a generator it will not execute like a normal function. It will execute to the point where it sees a yield statement and it will exit until you need a new value. When you want a new value, you ask the generator for the next value and it will execute the function again from where it left off until there are no more values to generate. In the following sections we will learn how to create generators, how to iterate over them, how to stop them and more.

Creating Generators

You can create a generator by placing a * after the function keyword:

// [lang]: js
function* myGenerator() {
 //...
}

Next, in the body of the generator function, we can generate values using the yield statement:

// [file]: code/generators/simple.js
function* simpleGenerator() {
  yield 1;
  yield 5;
}
const g = simpleGenerator();
const v1 = g.next().value; // --> 1
const v2 = g.next().value; // --> 5
const v3 = g.next().value; // --> undefined

You can even define an infinite loop and generate values:

// [file]: code/generators/inf-loop.js
function* myGenerator() {
  let i = 0;
  while(true) {
    i += 1;
    yield i;
  }
}

Now if it were a normal function, it would get stuck in an infinite loop. But because this is a generator we can read values generated by calling next on the generator object returned:

// [lang]: js
const g = myGenerator();
const v1 = g.next(); // --> { value: 1, done: false }
const v2 = g.next(); // --> { value: 2, done: false }
const v3 = g.next(); // --> { value: 3, done: false }
// and so on...

Essentially, we enter and exit the function every time we call next and we pick up from where we last left off. Notice how the value of i is "remembered" every time we call next. Now let's update the code above and make the generator finish generating values. Let's make it so that it won't generate any values if i is bigger than 2:

// [lang]: js
function* myGenerator() {
  let i = 0;
  while(true) {
    i += 1;
    if(i > 2) {
      return;
    }
    yield i;
  }
}

or we can simplify the code above and move the condition to the while loop:

// [file]: code/generators/inf-loop-terminate.js
function* myGenerator() {
  let i = 0;
  while(i < 2) {
    i += 1;
    yield i;
  }
}

Now if we read the generated values, we will only get two values out:

// [lang]: js
const g = myGenerator();
const v1 = g.next(); // --> { value: 1, done: false }
const v2 = g.next(); // --> { value: 2, done: false }
const v3 = g.next(); // --> { value: undefined, done: true }

Notice that after the second value, if we keep calling next, we will get the same result back. That is, a generator object with a value of undefined and the done property set to true indicating that there will be no more values generated.

Read more asyncjsbook.com