Introduction to Generators in ES6
Tags: javascript, es6, generators
Published: 2017-09-26 20:01:22

---
title: Introduction to Generators in ES6
published: true
description: Exploring generator functions in ES6
tags: javascript, es6, generators
canonical_url: https://www.damiencosset.com/generators/
---

## Introduction

With ES6, we were given a new tool: **generators**. In a normal function, there is only one entry point: the invocation of the function itself. A generator allows you to pause the execution of a function and resume it later. Generators are useful when dealing with iterators and can simplify the asynchronous nature of Javascript.

## Syntax

So, how would we define a generator, compared to a normal function? You declare a generator function by using the * ( asterisk ) operator after the *function* keyword:

```javascript
function* awesomeGenerator(){
  //code
}
```

To pause the execution inside the generator, we use the statement *yield*:

```javascript
function* awesomeGenerator(){
  yield 'Hey friend' // We pause the execution here
  console.log('Back again') // When we resume, we are here
}
```

## next() method

A generator gives you a *next()* method, which is used to start/resume the execution. This method returns an object with two keys:

```javascript
{
  value: [ yielded value ],
  done: [ true if we reach the end]
}
```

Let's see a very simple generator in action:

```javascript
function* groceriesGenerator(){
  yield 'Eggs'
  yield 'Tomatoes'
  yield 'Milk'
  return 'Paper Bag'
}

const groceries = groceriesGenerator()

console.log(groceries.next()) // [1]
console.log(groceries.next()) // [2]
console.log(groceries.next()) // [3]
console.log(groceries.next()) // [4]

// [1] { value: 'Eggs', done: false }
// [2] { value: 'Tomatoes', done: false }
// [3] { value: 'Milk', done: false }
// [4] { value: 'Paper Bag', done: true }
```
At our first *groceries.next()* call, our *groceriesGenerator* reached our first *yield* statement and paused, returning the value *Eggs* to the caller. Our second *next()* resumed the execution at the second *yield* statement, pausing it again and returning *Tomatoes*...

Our last *next()* terminates the generator, returns *Paper Bag* and sets *done* to true.

## As iterators

In the introduction, I said that generators could help to implement iterators. Let's see an example:

```javascript
function* iterationGenerator( arr ){
  for( let i = 0; i < arr.length; i++ ){
    yield arr[i]
  }
}

const iterator = iterationGenerator( ['John', 'Sarah', 'Joe', 'Emily'])

let current = iterator.next()

while( !current.done ){
  console.log( current.value )
  current = iterator.next()
}

// John
// Sarah
// Joe
// Emily
```

In this example, you can see how the state of the generator is maintained accross invocations. Whne we resume the execution by calling *next()*, the variables and loops are the same. 

## Pass values back to generators

Finally, you can also pass a value back to a generator. Here is a example:

```javascript
function* twoWayGenerator(arr){
  for( let i = 0; i < arr.length; i++ ) {
    const symbol = yield 
    console.log(`${arr[i]} ${symbol}`)
  }
}

const prices = twoWayGenerator([10, 23, 12])

prices.next()
prices.next('€')
prices.next('£')
prices.next('$')

// 10 €
// 23 £
// 12 $
```

Here, our first *next()* will not print anything because we pause the execution *before* the first console.log. The second *next()* is called with an argument. This argument is provided as the returned value of the yield statement. We store this value inside the *symbol* variable and use it next.

You can also force a generator to throw an error:

```javascript
prices.next()
prices.throw( new Error('Invalid Amount'))

//  const symbol = yield
//                   ^
//  Error: Invalid Amount
```


That's it for a quick and dirty introduction about generators. In the next article, we will go a bit deeper and explore how generators can help us control the asynchronous flow of Javascript.