Functional JavaScript — Generators
Tags: webdev, programming, javascript, functional
Published: 2021-01-25 01:35:34

**Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62**

**Subscribe to my email list now at http://jauyeung.net/subscribe/**


JavaScript is partly a functional language.

To learn JavaScript, we got to learn the functional parts of JavaScript.

In this article, we’ll look at JavaScript generators.

### Callback Hell

If we some functions like:

```
let sync = () => {
  //..
}
let sync2 = () => {
  //...
}
let sync3 = () => {
  //...
}
```

and each function is synchronous, then we can call it one by one and compose them our way.

But if they’re async, then we can’t call one by one.

An async function may have a callback to let us call the callback when we get the result:

```
let async1 = (fn) => {
  //...
  fn( /* result data */ )
}
let async2 = (fn) => {
  //...
  fn( /* result data */ )
}
let async3 = (fn) => {
  //...
  fn( /* result data */ )
}
```

Then if we want to call them sequentially, we’ve to write something like:

```
async1(function(x) {
  async2(function(y) {
    async3(function(z) {
      //...
    });
  });
});
```

As we can see, there’s a lot of nesting in our code.

We got to make this cleaner.

### Generators

We can clean up this code with generators.

To create a generator function, we can write:

```
function* gen() {
  return 'foo';
}
```

A generator function is indicated by the `function*` keyword.

Then we can call it to create a generator:

```
let generator = gen();
```

The `generatorResult` object has the `next` method to return the value we yielded.

The returned object has the `value` and `done` properties.

So we can write:

```
generator.next().value
```

and we get `'foo'` .

Calling `next` for a second time will return an object with the `value` being `undefined` .

The `yield` keyword is a new keyword that will bring value to the `next` method.

The value of each `yield` statement will return in the sequence they’re listed.

`yield` pauses the execution of the function and sends back the result to the caller.

Then next time `next` is called, the `next` yield statement is run.

So if we have:

```
function* gen() {
  yield 'first';
  yield 'second';
  yield 'third';
}

let generator = gen();
```

The first `generator.next()` call returns:

```
{value: "first", done: false}
```

Then 2nd call returns:

```
{value: "second", done: false}
```

The 3rd call returns:

```
{value: "third", done: false}
```

The 4th call returns:

```
{value: undefined, done: true}
```

which indicates that the generator has no more values to return.

The `done` property indicates whether the generator bis done with returning all the values.

We know when to stop calling `next` once `done` is `true` .

### Passing Data to Generators

We can also pass data to generators.

To do that, we create a generator function with a `yield` statement that has no value after it.

For example, we can write:

```
function* fullName() {
  const firstName = yield;
  const lastName = yield;
  console.log(`${firstName} ${lastName}`);
}
```

We have the `yield` statement without a value after it, so it’ll accept values we pass into `next` .

Then we can use it by writing:

```
const fn = fullName();
fn.next()
fn.next('mary')
fn.next('jones')
```

We create the generator function.

Then we call `next` to start the generator.

Once we did that, we can start passing values into the generator.

We call:

```
fn.next('mary')
```

to pass in a value to the first `yield` statement.

Then we do the same with the 2nd one with:

```
fn.next('jones')
```

Once we did that, we get `'mary jones'` from the console log.

### Async Code and Generators

The `async` and `await` syntax is created based on generators.

For instance, we can use it by writing:

```
const getData = async () => {
  const res = await fetch('https://api.agify.io/?name=michael')
  const data = await res.json();
  console.log(data);
}
```

We have the `async` and `await` syntax.

`await` pauses the execution of `getData` until the result is present.

So it acts like `yield` .

Now we run our async code line by line.

The only difference is that `await` only works with promises.

### Conclusion

We can use generators to return items in sequence.

The function is paused after a result is returned and resumed when the next result is requested.

The `async` and `await` syntax for promises is based on the generator syntax.