What the... generators!

May 08, 2018 0 Comments

What the... generators!

 

 



Want to know about generators?

FIRST you need to check iterators

That's not something you can skip, because, generators work through iterators. We can say that generators are a simpler way to write our own iterators.

This is a generator:

 
function breeds(){ yield "labrador"; return "chow-chow";
} const iterator = breeds(); console.log(iterator.next())
//->{value: "labrador", done: false}
console.log(iterator.next())
//->{value: "chow-chow", done: true}
console.log(iterator.next())
//->{value: undefined, done: true}

Let's see what's happening here.

First, we need to create a generator function, and we can do that by using a between function and the function name.
No matter if it's:


function* breeds()



function breeds()

const breeds = function *()

const breeds = function
()

This will work anyway!.

(But, It's a standard to use the just after the function ... so try to always use the syntax function.)

Inside that function we're using that yield ... what's that?

yield It's something listening to the next() calls.

Everytime we use the .next() on the iterator, the generator will use the next not yet used yield.

That's the same idea behind iterators and we're checking that, with the done key the iterators returns!.

If It's value is false the .next() will call the yield AFTER the previous one.

 
console.log(iterator.next())
//->{value: "labrador", done: false}
console.log(iterator.next())
//->{value: "chow-chow", done: true}
console.log(iterator.next())
//->{value: undefined, done: true}

When the done:true will happens?

When there's no more to yield out that generator.

But we need to be more precise about this.

focus

We all know that a function, in JS, always returns something.

If you do not define a return, JS will do It for you, by returning an "undefined" at the end of It.

 
function breeds(){ yield "labrador"; yield "chow-chow";
} const iterator = breeds(); console.log(iterator.next())
//->{value: "labrador", done: false}
console.log(iterator.next())
//->{value: "chow-chow", done: false}
console.log(iterator.next())
//->{value: undefined, done: true}

By taking away the return from the function, calling .next() will force JS to return a {value: undefined, done: true}

So JS still returns It for you, also with generators, because, we're still talking about functions here!

If you want to force a return you can use the .return() method on the iterator and finish the generator.

 
function
breeds(){ yield "labrador"; yield "chow-chow";
} const iterator = breeds(); console.log(iterator.return("we <3 dogs"))
//->{value: "we <3 dogs", done: true}
console.log(iterator.next())
//->{value: undefined, done: true}
console.log(iterator.next())
//->{value: undefined, done: true}

As you can see, we're immediately returning and finishing the generator with the .return() method!.

generators are not magic!

We're really not executing stuff by calling the generators ... indeed, we're using the iterator interface every time we're calling generators with the .next() method.

We can see the .next() as a remote controller to START (calling yield) and PAUSE (checking the done: value) the generator function

That's why, we need to define:

 
const iterator = breeds();

and call the iterator.next()

(iterator It's just the variable name, not the iterator object itself)

lot of stuff can be done

In real life work, we can do really lot of stuff with generators.

We can use generators values with variables.

We can fetch, spread and use the for...of loop.

At the moment we're using generators to call one single yield at time, we can say, that we're using It in synchronous way.

But, generators can be also used in asynchronous way.

I'm not going to cover It now... you can check about Promises or async/await, and maybe, we we'll talk about that, another day.

Promises

Async

HAVE FUN WITH CODE
Pearl Jam


Tag cloud