[JavaScript – ES2015] Generators

“Generator” is a construct to create iterator object. The main usage of generators is to implement “await” like async programming. Redux-saga is the best example of using generators as internal implementation.

 

1. Syntax

Yes, it is weird. The “function*” and “yield” keywords are used to declare generators.

The generator function – with the “*” – returns an iterator. Let’s prove this.

let numbers = function* () {
  yield 1;
  yield 2;
  yield 3;
};
let iterator = numbers();
let next = iterator.next();
while (!next.done) {
  console.log(next.value);
  next = iterator.next();
}

 

Creating a custom iterator is quite cumbersome because you need to maintain the current location and check the next value. Generators make this process much easier.

 

2. for..of

Generators can be used with for..of loop.

 

3. yield and async

When a generator yields a value, the generator suspends the execution until the next() is called. This makes generators as the basic building block of async programming.

let numbers = function* (max) {
  for (let i = 1; i <= max; i++) {
    console.log('yield: ' + i);
    yield i;
  }
};
for(let num of numbers(3)) {
  console.log(num);
}

Check the Console screen.

yield: 1
1
yield: 2
2
yield: 3
3

Calling a generator function does not return all values at once.

 

4. Custom Iterator class with Generator

To create a custom iterator, you need to implement the [Symbol.iterator] method. The “*” symbol is placed before the function name.

class Worker {
  constructor() {
    this.tasks = [];
  }
  addTask(task) {
    this.tasks.push(task);
  }
  *[Symbol.iterator]() {
    for (let task of this.tasks) {
      yield task;
    }
  }
}

let worker = new Worker();
worker.addTask(() => {
  console.log('task 1');
});
worker.addTask(() => {
  console.log('task 2');
});
worker.addTask(() => {
  console.log('task 3');
});

for (let task of worker) {
  task();
  console.log('task done');
}

The result is like this:

task 1
task done
task 2
task done
task 3
task done

Tasks are chained just like using the Promise pattern.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s