How to Use Generator and Yield in JavaScript

How to Use Generator and Yield in JavaScript

livecodestream.dev livecodestream.dev2 weeks ago in #Dev Love67

Some time ago I wrote an article explaining the concept of generators and how to use them in Python, but did you know that JavaScript has its own version of generators? This is actually a concept many people who develop JavaScript apps didn’t know it existed, so today we are going to introduce generators in JavaScript. What are generators? With ES6 we got introduced to great new functionality like arrow functions, spread operators, and generators among others, but what is a generator? A generator is a function that contrary to normal functions allows for the function to be exited and later re-entered with its context (variable bindings) preserved across re-entrances. Let’s break that down and look into generators step by step so that we can all understand how they work. When we execute a regular function, the interpreter will run all the code into that function until the function is completed (or throws an error). This is known as the run-to-completion model. Let’s take an example of a very simple function: function regularFunction() { console.log(“I’m a regular function”) console.log(“Surprise surprice”) console.log(“This is the end”) } regularFunction() —————– Output —————– I’m a regular function Surprise surprice This is the end Nothing fancy yet, just as you expected is a regular function that’s executing until it reaches the end or returns a value. But what if we just want to stop the function at any point to return a value, and then continue? That’s when generators enter the picture. My first generator function function* generatorFunction() { yield “This is the first return” console.log(“First log!”) yield “This is the second return” console.log(“Second log!”) return “Done!” } Before we execute that function you may be wondering about a few things, first what is function*? That’s the syntax we use to declare a function as a generator. And what about yield? The yield, in difference to a return, will pause the function by saving all its states and will later continue from that point on successive calls. In both cases, the expression will be returned to the callers’ execution. What did exactly happened to our function as such? Let’s find out by calling the function: generatorFunction() —————– Output —————– generatorFunction {} { __proto__: Generator [[GeneratorLocation]]: VM272:1 [[GeneratorStatus]]: “suspended” [[GeneratorFunction]]: ƒ* generatorFunction() [[GeneratorReceiver]]: Window [[Scopes]]: Scopes[3] } Wait, what? When we call a generator function the function is not automatically triggered and instead, it returns an iterator object. What’s particular about this object is that when the method next() is called, the generator function’s body is executed until the first yield or return expression. Let’s see it in action: const myGenerator = generatorFunction() myGenerator.next() —————– Output —————– {value: “This is the first return”, done: false} As explained the generator run until the first yield statement and yielded an object containing a value property, and a done property. { value: …, done: … } The value property is equal to the value that we yielded The done property is a boolean value, which is only set to true once the generator function returned a value. (not yielded) Let’s invoke next() one more time and see what we get myGenerator.next() —————– Output —————– First log! {value: “This is the second return”, done: false} This time we first see the console.log in our generator body being executed and printing First log!, and the second yielded object. And we could continue doing this like: myGenerator.next() —————– Output —————– Second log!  » Read More

Like to keep reading?

This article first appeared on livecodestream.dev. If you'd like to keep reading, follow the white rabbit.

View Full Article

Leave a Reply