Generators~ Basics ~

Generators

Like the iterable protocol, using generators in JavaScript is not very popular. The community is not betting a lot on this API. I think that it has potential, especially for handling asynchronous processes.

The generator functions are a special type of function that returns an iterable generator if called. This means that the code inside the function is not executed immediately. We have to call the next method of the generator. Then the execution continues until a yield statement appears. The following code snippet illustrates the workflow:

function* calculate() {
  yield 10;
  const result = yield 5;
  console.log(`Result = ${result}`);
}

const g = calculate();
const res1 = g.next(); // {value: 10, done: false}
const res2 = g.next(); // {value: 5, done: false}
g.next(res1.value + res2.value); // Result = 15

Let's read this example line by line and explain what happens:

The ability of the generator to send and receive data is what makes it unique and opens the door for some interesting implementations. The most common one is the implementation of the command pattern. Think about how we have to do something which consists of a couple of steps. For example, we want to get an image URL from a remote server and create an <img> tag. Here is how this looks like with a generator.

commander(robot());

function* robot() {
  const catURL = yield ["get-cat"];
  const imgTag = yield ["format", catURL];
  console.log(imgTag);
}
async function commander(gen, passBack) {
  let state = gen.next(passBack);
  switch (state.value ? state.value[0] : null) {
    case "get-cat":
      const res = await fetch("https://api.thecatapi.com/v1/images/search");
      const data = await res.json();
      return commander(gen, data[0].url);
    case "format":
      return commander(gen, `<img src="${state.value[1]}" />`);
  }
  if (!state.done) {
    commander(gen);
  }
}

// after a second or two we'll get:
// <img src="https://cdn2.thecatapi.com/images/<random id here>.jpg" />

Our generator function robot sends commands out and asynchronously receives results. get-cat is a command that performs an HTTP request to thecatapi.com and returns a random image URL. format is another command and it returns the image tag. Also, the generators, similarly to the async/await syntax, make our functions look synchronous.