Introduction to Generators in JavaScript
Tags: javascript
Published: 2021-08-05 08:37:56

Generators are an advanced concept in javascript but are quite easy to understand. Generators are special functions in javascript which can return multiple values on demand unlike regular functions which can only return one value. 

Unlike normal functions, the execution of a generator function can be stopped **midway** and can be resumed. 

## How to create a generator function

There is a special syntax for creating a generation function which is not much different from the normal function syntax.

```jsx
function* generatorFunction(){

}
```

The * after the function keyword is what makes this function a generator function. 

## How to use the generator function created above

Another keyword yield is introduced here. You can think of yield as the return keyword but for generator functions. Let's take an example here

```jsx
function* generatorFunction(){
		console.log("Start")
		yield 7;
		console.log("Midway")
		yield 8;
		console.log("Stop")
}

const gen = generatorFunction();

let result = gen.next();
console.log(result.value) // logs 7
result = gen.next();
console.log(result.value) // logs 8
```

Let's see what's happening here:

1. We define a generator function which first yields (returns) the number 7 and then next yields the number 8. We also added a couple of console logs.
2. We call the generatorFunction here and store the return value in the variable `gen`
3. Normally when using normal functions you will expect the `gen` variable to hold the value 7. 
4. But that's not the case for generators.  The `gen` variable doesn't store the value yielded by the generator, instead it stores a `Generator` object returned by `generatorFunction`
5. The `gen` object has a method `next()` 
6. The first call of the `gen.next()` method starts the execution of the generator function and when it reaches a `yield`, it stops the function there and returns an object which has 2 properties `value` and `done`.   **Value** is the yielded value and **done** is a boolean which tells us whether the generator function is done completely executing or not
7. So in the above example, when `gen.next()` is called for the first time, the generator function starts executing. "Start" is logged to the console and then the generator yields a value of 7. That's when it stops the function and returns an object, which (in this case) will be `{ value : 7 , done : false }`. **value** is the yielded value which is 7. **done** is `false` because the generator is not completely executed yet; there are still some lines of code in the function yet to be executed. "7" is logged to the console.
8. The next (second) call of the `gen.next()` method resumes the generator function from the point it stopped at before. Thus, "Midway" is logged to the console and then the generator yields a value of 8. It stops the function there and returns  `{ value: 8, done: false}` since the yielded value is 8 and the function is still not done executing. "8" is logged to the console.
9. "Stop" is never logged to the console since we never call `gen.next()` again

### Notes

- In the above example, if we call `gen.next()` for a third time, "Stop" will be logged on the console and the object returned would be `{value : undefined, done : true}`. Notice how this time the done property is true? That's because all the code of the generator is done executing. Whereas the value property is undefined? That's because no value has been yielded by the generator. If you keep calling `gen.next()` after this, the result will always be `{value : undefined, done : true}`
- A generator object cannot be restarted. Once it's done completely executing, you cannot restart it. If you want to run a generator function again make a new `Generator` object by calling `generatorFunction` and store it in a new variable. Then you can work with that variable.
    - Example :

        ```jsx
        const newGen = generatorFunction();

        const newResult = newGen.next():

        console.log(newResult).value) // logs 7
        ```