JavaScript Generator Functions
Tags: javascript, generator
Published: 2020-03-29 03:27:00

When starting the studying about React, we need learning some concepts like: components, properties and state. So, we see that a component has a internaly state and when that state change the component is rerendered. However some times we need share some information between our components, like user information or a shoopping cart and, for that we can use a manager state like Redux.

[Redux is a state container for JavaScript apps](https://redux.js.org/introduction/getting-started), that to lead with [assyncrounous operations](https://redux.js.org/advanced/async-actions#async-action-creators) needs a middleware, Like Redux Thank or Redux Sagas as example.

In the Redux Sagas [getting start](https://redux-saga.js.org/docs/introduction/BeginnerTutorial.html) we can see an example of a saga:

```javascript
export function* helloSaga() {
  console.log("Hello Sagas!");
}
```

As a documentation say: the only thing that can be weird is `*`. This symbol is a way we can creating a Generator.

# Generator

Generators are functions that their processing can be stoped and resumed. When we create and execute a generator function, that do not work as a normmal function. The normal, when executed can return a single value or nothing.

```javascript
function normalFunction() {
  return singleValue;
}
```

However when we call a generator function we will receive an object that can be used to control the process.

```javascript
function* generateFunction() {
  yield "first";
  yield "second";
  return "third";
}

const objectGeneratorControl = generateFunction();
```

The object to control the generator processes has a method called _next_, this method when called initialize the generator flow:

```javascript
function* generateFunction() { /* (INIT) Call of generateFunction() */
  console.log("First next() call");  
  yield "first"; /* (1) First call objectGeneratorControl.next() */
  yield "second"; /* (2) Sencond call objectGeneratorControl.next() */
}

const objectGeneratorControl = generateFunction(); /* Generator creating*/

console.log(objectGeneratorControl.next());
console.log(objectGeneratorControl.next());
console.log(objectGeneratorControl.next());
```

In the initial moment, when we call `generateFunction()`, the generator flow is initialized and a pointer is stoped at top (**INIT mark**). Thus, the `console.log("First next() call")` is not executed yet.

The **console.log** inside the generator function will be executed when we call for the first time the **next** method. So, the execution will runs until the "first" yield and return an object with the shape:

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

In this object, the property value, represents the yielded value and the **done** property say that the function not yet finished. Calling the **next method** again, it will produce:

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

However, whether we call **next method** again the result will be:

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

This object tells us that the function has come to the end and without any value. However, we can specify a value by include a return statement:

```javascript
function* generateFunction() {
  yield "first";
  yield "second";
  return "end";
}
```

## Generator as Iterables

Iterables objects, in JavaScript, are objects that have a next() method returning an object like:

```typescript
{
  "value": any
  "done": boolean
}
```

We can iterate over this objects easily using the `for ... of` statement, as an example we have that arrays are iterables.

```typescript
const it = [1, 2, 3, 4, 5];

for (const iterator of it) {
  console.log(iterator);
}
```

So when we need iterate over a object, its iterator method is called, however only some built-in objects have the iterator method. Thus, if we need iterate over an object that do not has the iterator method, we can add it easily with generator.

```javascript
const object = {
  begin: 1,
  end: 5,

  [Symbol.iterator]: function*() {
    for (; this.begin <= this.end; this.begin++) {
      yield this.begin;
    }
  }
};

for (const iterator of object) {
  console.log(iterator);
}
```

## Generator as Data producer and consumer

As we see previously, a generator can produce values with the yield. However, for consume some data, this is made through the next method call. That is, it method accept a paramater wich will be the internal return of yield statement.

```javascript
objectGeneratorControl.next("value");
```

However, the first call of **next** method will only "initialize" the generator flow. That is, this value passed to generator will be verified from the second **next** method calling.

```javascript
function* generateFunction() {
  let valuePassedCameFromNextMethod;

  console.log(`First next method call:`);
  valuePassedCameFromNextMethod = yield "first";
  console.log(`Second next method call: ${valuePassedCameFromNextMethod}`);
  valuePassedCameFromNextMethod = yield "second";
  console.log(`Third next method call: ${valuePassedCameFromNextMethod}`);
  return "end";
}

const objectGeneratorControl = generateFunction();

console.log(objectGeneratorControl.next("Initializing"));
```

Executing the above code we will see the yielded object: { value: 'first', done: false }. But, the flow will stop at this point and thus the value passed to **next** method will be viewd inside the generator from the second call.

```javascript
console.log(objectGeneratorControl.next("Now go"));
```

Will result:

```text
Second next method call: Now go
{ value: 'second', done: false }
```

In this post, sought to carry out a little introduction about Generators that is a powerful tool to lead with multitasks due the possibilite of pause and resume the Generator. So, that feature gives the possibility of greater control of tasks, as we can see the [reason of Redux Saga uses Generator](https://github.com/redux-saga/redux-saga/issues/987#issuecomment-301039792).

**Sources**

https://github.com/gajus/gajus.com-blog/blob/master/posts/the-definitive-guide-to-the-javascript-generators/index.md
https://exploringjs.com/es6/ch_generators.html#sec_generators-as-observers
https://2ality.com/2015/03/es6-generators.html
https://javascript.info/generators
https://davidwalsh.name/es6-generators
https://github.com/redux-saga/redux-saga/issues/1373
https://github.com/redux-saga/redux-saga/issues/987#issuecomment-301039792
https://tc39.es/ecma262/#sec-generator-function-definitions