loading...
Cover image for Understanding Generators in ES6 Javascript

Understanding Generators in ES6 Javascript

phung_cz profile image Tuan Phung ⚡️ Updated on ・2 min read

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

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() {
  ...
}

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.
}

Creating the iterator

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

const iterator = avengersGenerator();

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}

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}

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 ✌

Posted on by:

phung_cz profile

Tuan Phung ⚡️

@phung_cz

Frontend developer @ Mews / Creator of pandacolors.com and devjobs.cz / Professional rice eater

Discussion

pic
Editor guide
 

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

 

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

 

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

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...

 

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.

 

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

 

redux-sagas used a lot of generator functions

 

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
}
 

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...

 

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.

 

Nice catch, just fixed that, thanks ;)

 

I didn't know about generators! interesting!

 

I hope that you will try them out!

 

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

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...

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 :)

 

Typo in code snippet: yeild "Spider man";

 
 

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 😓

 

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

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

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


 

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.

 

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...

 

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

 

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

 

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...

 

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?

 

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