DEV Community

Cover image for Understanding Generators in ES6 Javascript
Tuan Phung ⚡️
Tuan Phung ⚡️

Posted on • Updated on

Understanding Generators in ES6 Javascript

Maybe you have heard about this feature in ES6 or you just didn’t have time to play with it.

It is something, that I have learned a few days ago and it's super cool.

Let me explain it to you in a few steps.

So Generators looks like a normal function, but it allows us to pause the execution of the function and continue it later.

So below you can see an example of the generator and we will break it down to see how it works:

function* avengersGenerator() { // Declaring the generator
  yield "Hulk"; // Pausing the execution
  yield "Thor";
  yield "Iron man";
  return "Ultron"; // Example of finishing the generator
  yield "Spiderman";
}

const iterator = avengersGenerator(); // Creating iterator

iterator.next(); // Iterating on the generator

Enter fullscreen mode Exit fullscreen mode

Source code on codesandbox.io

Declaring the generator

Generators look similar to a normal function, the only difference is we have to define an * (asterisk) after the word function.

function* avengersGenerator() {
  ...
}
Enter fullscreen mode Exit fullscreen mode

Yield it!

We can yield the function, which basically would stop the execution of the function when it gets to the first yield.

function* avengersGenerator() {
  yield "Hulk" // The execution would pause here.
  yield "Iron man" // When we resume we would start here.
}

Enter fullscreen mode Exit fullscreen mode

Creating the iterator

On iterator, we can call. So by this, we will prepare our generator for action.

const iterator = avengersGenerator();
Enter fullscreen mode Exit fullscreen mode

Next method

This enables us to continue the execution of the function. Also, this method provides us with the object with the yielded value and whether the generator has yielded its last value, as a boolean.

iterator.next(); // [1] Object {value: "Hulk", done: false}
iterator.next(); // [2] Object {value: "Thor", done: false}
iterator.next(); // [3] Object {value: "Iron man", done: false}
iterator.next(); // [4] Object {value: undefined, done: true}
Enter fullscreen mode Exit fullscreen mode

Return / Exiting

Once a return is being called, it would finish the generator. It basically sets the done property to true.

function* avengersGenerator() {
  yield "Hulk";
  return "Ultron"; // Example of finishing the generator
  yield "Thor"; //  Sad Thor and Spiderman wouldn't be called
  yield "Spiderman";
}

iterator.next(); // [1] Object {value: "Hulk", done: false}
iterator.next(); // [2] Object {value: "Ultron", done: true}
Enter fullscreen mode Exit fullscreen mode

In my opinion, generators are quite a cool thing to play with or at least to know what it does.

In the next post, I will explain, how generators helped me to solve one case at my work thanks to the possibility to cancel the promise when needed with generators in ES6.


UPDATE 1: I finally got some time to write another blogpost about generators, so here it goes 👉 Canceling promises with generators in ES6 Javascript


Thanks for reading

Let me know in the comments section how you feel about this generators series. If you love it, you know what to do! Share it with your friends and colleagues.

If you want me to cover some topics in the next post, DM me on here on dev.to or on twitter @phung_cz, or if you have any suggestions, feel free to comment below.

See ya next time and keep on hacking ✌

Top comments (27)

Collapse
 
adam_cyclones profile image
Adam Crockett 🌀

I understand how they work, but I still have no idea where to use a generator.

Collapse
 
tuanphungcz profile image
Tuan Phung ⚡️

I will write another post with examples where generators come in handy

Collapse
 
adam_cyclones profile image
Adam Crockett 🌀

Seems people agree. Unrelated: I also hate that you can't restart a generator. Despite the initial spec saying you could.

Thread Thread
 
tuanphungcz profile image
Tuan Phung ⚡️

I finally got some time, so I wrote down one example for the usage of generators, hope that you'll enjoy reading it 👉dev.to/phung_cz/canceling-promises...

Collapse
 
rtk profile image
RouvenKruse

The only scenario I can think of is using an asynchronous generator in combination with the "for await ... of" loop (developer.mozilla.org/en-US/docs/W...) when not using libraries such as rxjs.

Collapse
 
adam_cyclones profile image
Adam Crockett 🌀

Interesting! I didnt know about for await of and I thought I had mastered async await :/

Collapse
 
zee786 profile image
zee786

redux-sagas used a lot of generator functions

Collapse
 
burdier profile image
Burdier • Edited

i did a very simple example:

function* AppleSale()
{
  var apple = 10;
  while(apple)
    yield apple--;
}

let sale = AppleSale();

console.log(`on stock ${sale.next().value}`);
console.log(`on stock ${sale.next().value}`);
console.log(`on stock ${sale.next().value}`);
//output:
//on stock 10
//on stock 9
//on stock 8
}
Collapse
 
tuanphungcz profile image
Tuan Phung ⚡️

I finally got some time, so I wrote down one example for the usage of generators, hope that you'll enjoy reading it 👉dev.to/phung_cz/canceling-promises...

Collapse
 
danielescoz profile image
Daniel Escoz

You have an error in your return example: the value you return will be returned by the iterator's next call as a single {value: "Ultron", done: true}, not in two distinct steps.

Also, undefined should be between quotes, it's not a string but a specific value.

Collapse
 
tuanphungcz profile image
Tuan Phung ⚡️

Nice catch, just fixed that, thanks ;)

Collapse
 
kurisutofu profile image
kurisutofu

I didn't know about generators! interesting!

Collapse
 
tuanphungcz profile image
Tuan Phung ⚡️

I hope that you will try them out!

Collapse
 
kurisutofu profile image
kurisutofu

I will research them and probably will try to use them!
And I'll wait for the next article you mentioned in this one ;)

Thread Thread
 
tuanphungcz profile image
Tuan Phung ⚡️

I finally got some time, so I wrote down one example for the usage of generators, hope that you'll enjoy reading it 👉dev.to/phung_cz/canceling-promises...

Thread Thread
 
kurisutofu profile image
kurisutofu

I just read it and it was nice but to be honest, I still have trouble grasping how it could be more beneficial than other methods.
It's Monday and I haven't played with it so I'll revisit your article later and it will probably make more sense to me :)

Collapse
 
larsklopstra profile image
Lars Klopstra ⚡

Typo in code snippet: yeild "Spider man";

Collapse
 
tuanphungcz profile image
Tuan Phung ⚡️

Fixed, thanks!

Collapse
 
k3rnel_err0r profile image
Antonio Quintero-Felizzola

Loved the article! I was wondering if we can use more combinations in the yield part . I don't know, maybe callbacks? Is it possible?

function* avengersGenerator() {
  yield "Hulk";
  yield greeting
  yield "Spiderman";
}

function greeting() {
  console.log("Hi, Tuan!")
}

I have not tested it yet 😓

Collapse
 
tuanphungcz profile image
Tuan Phung ⚡️ • Edited

yes, we can! You need to any function there ;)

function greeting() {
  console.log("Hi, Antonio!")
}

function* avengersGenerator() {
  yield "Hulk";
  yield greeting()
  yield "Spiderman";
}


Collapse
 
fpuffer profile image
Frank Puffer

Looking forward to your next post. What you have shown so far can be achieved much more easily with a simple array but I am sure there are better use cases for generators. I guess it gets more interesting when you don't know in advance how many values need to be generated.

Collapse
 
tuanphungcz profile image
Tuan Phung ⚡️

I finally got some time, so I wrote down one example for the usage of generators, hope that you'll enjoy reading it 👉dev.to/phung_cz/canceling-promises...

Collapse
 
cuongbphv profile image
Cuong Bui • Edited

Thanks guy for sharing. Hope you write an article, how to apply generator for real usecases. Thanks again! And we can keep contact because I see your Vietnamese name :D

Collapse
 
tuanphungcz profile image
Tuan Phung ⚡️

Hey, haha sure, feel free to follow me on dev.to :D

Collapse
 
tuanphungcz profile image
Tuan Phung ⚡️

I finally got some time, so I wrote down one example for the usage of generators, hope that you'll enjoy reading it 👉dev.to/phung_cz/canceling-promises...

Collapse
 
rohovdmytro profile image
Rohov Dmytro

Nice post, but I am wondering where to apply generators in real world.

What I got is that async / await syntax «abstracts» this stuff or it is not the case?

Collapse
 
tuanphungcz profile image
Tuan Phung ⚡️

Yep, will write about it in my next post ;)