Javascript Generators

ES6 brought a bunch of new functions to deal with asynchronous data streams. Generator functions and async/await syntax among them.

Generators are special kind of function that can be paused and then resumed.

Declaring Generator Function

Generators are defined using function keyword with asterisk *:

function* generator() {
  // This is generator function
}

Inside generator function you can use new keyword yield. It works kind of like return but instead of stopping function completely it pauses it so you can continue execution from that place later.

function* generator() {
  console.log("This will output first.");
  yield;
  console.log("This will output only after you resume.");
}

Controlling Generator Function

Calling generator function doesn’t execute it’s body immediately. Instead it returns an iterator, an object that contains method next(). Every time you’ll call this method it will unpause the generator function so it will be executed until next yield or return keyword.

function* generator() {
  return "Hey!";
}

const iterator = generator();

console.log(iterator.next()); // {value: "Hey!", done: true}

Every time you call next() on your iterator it will return and object with value and done fields. value will contain what you pass to your yield or return, and done signifies if function finished execution.

function* sampleGenerator() {
  yield "Just paused.";
  return "Now stopped.";
}

const iterator = sampleGenerator();

console.log(iterator.next()); // {value: "Just paused.", done: false}
console.log(iterator.next()); // {value: "Now stopped.", done: true}

Passing Data To Generator Function

You can also pass data back to your generator function.

To do this just call next() method of your iterator with an argument.

function* sampleGenerator() {
  const time = yield "Hey, what time is it?";
  return `It's ${time} o'clock.`;
}

const iterator = sampleGenerator();

console.log(iterator.next()); // {value: "Hey, what time is it?", done: false}
console.log(iterator.next("16:20")); // {value: "It's 16:20 o'clock.", done: true}