Generator Functions in JavaScript
Tags: javascript, webdev
Published: 2020-03-29 18:09:32



With ES6, EcmaScript releases a new way of working with the functions. In this article we will take a look at them and how and where we can use them

*****

**What are the generator functions?**

Generator functions are a special type of function which allows you to suspend their execution and later resumed at any time. Thye have also simplified the creation of iterators but we will get into that later. Let’s start simply by understanding what they are with some examples.

Creating a generator function is simple. The `function*` declaration (`function` keyword followed by an asterisk) defines a generator function.

    function* generatorFunction() {
       yield 1;
    }

Now, in generator functions, we don’t use return statements but rather a `yield` which specifies the value to be returned from the iterator. Now in the above example, it will return us a value of 1. Now, when we call generator functions like a normal ES6 function it does not directly execute the function but rather returns a `Generator` object. The `Generator` object contains `next()`, `return` and `throw` which can be used to interact with our generator functions. It works similarly to an `iterator` but you have more control over it. Let’s see with an example of how we can use `generatorFunction`. Now, as I told you before we get `next()`. Now, the `next()` method returns an object with two properties `done` and `value`. You can also provide a parameter to the `next` method to send a value to the generator. Let’s see this with an example.

    function* generatorFunction() {

    yield 1;

    }

    const iterator = generatorFunction()
    const value=iterator.next().value
    console.log(value)

![](https://cdn-images-1.medium.com/max/800/1*CuDQhYcZ3xLZKvFTosFFrg.png)


Now, as I said earlier that we can also pass values to the generator function through `next` and that value can be used inside `generator` the function. Let’s see how that works with another example.

    function* generatorFunction() {

    let value = yield null

    yield value+ 2;

    yield 3 + value

    }

    const iterator:Generator = generatorFunction()
    const value=iterator.next(10).value // returns null
    console.log(iterator.next(11).value) //return 13

![](https://cdn-images-1.medium.com/max/800/1*ywIGvmfO_r3j0rTdccplEQ.png)


<br> 

Now, here when you obtain the generator you don’t have a yield you can push values to. So first you have to reach a yield by calling the next on the generator initially. It will return `null` always. You can pass arguments or not it does not matter it will always return `null`. Now, once you have done that you have a `yield` at your disposal and you can push your value via `iterator.next()` which will effectively replace `yield null` with the input passed through `next` and then when it finds another `yield` it returns back to the consumer of the generator which is our `iterator` here.

Now, let’s talk a little about the `yeild` keyword. Here, it looks like it’s working like return but on steroids because return simply returns a value from a function after a function is called and it will also not allow you to do anything after `return` keyword in a normal function but in our case `yield` is doing much more than that it’s returning a value but when you again call it, it will move on to the next `yield` statement. The `yield` keyword is used to pause and resume a generator function. The `yield` returns an object and it contains a `value` and `done`. The `value` is the result of the evaluating of the generator functions and the `done` indicates whether our generator function has been fully completed or not, its values can be either `true` or `false`. We can also use `return` keyword in generator function and it will return the same object but it will not go any further than that and the code after return will
never be reached even if you have 6 `yield` after that so you need to be very careful using the `return` and should only be used once you are certain the job of the generator function is done.

    function* generatorFunction() {

    yield  2;

    return 2;

    yield 3; //generator function will never reach here

    }

    const iterator:Generator = generatorFunction()

<br> 

*****

### Uses of Generator Function

<br> 

Now, generator functions can very easily simplify the creation of iterators, implementation of the recursion or better async functionality. Let’s look at some examples.

    function* countInfinite(){

    let i=0;

    while(true){

    yield i;

    i++

    }

    }

    const iterator= countInfinite()

    console.log(iterator.next().value)

    console.log(iterator.next().value)

    console.log(iterator.next().value)

![](https://cdn-images-1.medium.com/max/800/1*YVzFY7yj2GwKBQUKbnhkug.png)


In the above, it’s an infinite loop but it will only be executed as many times as we call `next` on the iterator and since it preserves the previous state of the function it continues to count. This is just a very basic example of how it can be used but we can use more complex logic inside the generator functions giving us more power.

    function* fibonacci(num1:number, num2:number) {

    while (true) {

    yield (() => {

    num2 = num2 + num1;

    num1 = num2 - num1;

    return num2;

    })();

    }

    }

    const iterator = fibonacci(0, 1);

    for (let i = 0; i < 10; i++) {

    console.log(iterator.next().value);

    }

![](https://cdn-images-1.medium.com/max/800/1*UOMv0GIOFyRWOqhFMSxgMA.png)


Now in the above example, we implemented a Fibonacci series without any
recursion. The generator functions are really powerful and are only limited by your own imagination. Another big advantage of generator functions is that they are really memory efficient. We generate a value that is needed. In case of a normal function, we generate a lot of values without even knowing whether we are going to use them or not. However, in the case of the generator function, we can defer the computation and only use it when needed.

Now before using the generator function just keep some things in mind that you cannot access a value again if you have already accessed.

### Conclusion

Iterator functions are a great and efficient way to do a lot of things in
javaScript. There are many other possible ways of using a generator function.
For example, working with asynchronous operations can be made easy, now since a generator function can emit many values over time it can be used as an observable too. I hope this article helped you understand a little about `generator` function and let me know what else you can or are doing with the `generator` function.