Recently, I’ve had to pick up some JavaScript concepts to better reaffirm my understanding before moving on to work with them in React, and Generators was one of those concepts I had some little unrest understanding. I decided to piece together the basics to serve as a beginner’s working guide to generators.
Introduction: What are Generators?
According to the MDN resource
Generators are functions that can be exited and later re-entered. Their context (variable bindings) will be saved across re-entrances.
Generator functions are similar to regular functions, except that they can be paused and resumed. Generators are also very closely related to iterators, in the sense that a generator object is an iterator.
Comparison; Generators and Functions
A regular function such as the one below cannot be stopped before it finishes its task i.e. its last line is executed. It follows something called the run-to-completion model.
function regularFunction() {
console.log('There')
console.log('is')
console.log('no')
console.log('stopping')
console.log('me')
}
The only way to exit the regularFunction
is by using a return
statement or throwing an error. If you call the function again, it will begin the execution from the top again.
In contrast, a generator is a function that can stop midway and then continue from where it stopped. See the illustration below;
Syntax
Generator functions are created using a special syntax by adding an * after the function
keyword just like this function *
, and can be paused using the yield
keyword.
Calling a generator function initially does not execute any of its code; instead, it returns a generator object. Code is only executed and values are returned only when the generator’s next()
is called, which then executes code until it encounters the yield
keyword, upon which it pauses, until next()
is called again.
function * createGenerator() {
yield 'This';
yield 'is';
yield 'a';
yield 'Generator';
}
const generator = createGenerator(); // assigning the Generator function to the generator constant
generator.next(); // { value: 'This', done: false }
generator.next(); // { value: 'is', done: false }
generator.next(); // { value: 'a', done: false }
generator.next(); // { value: 'Generator', done: false }
generator.next(); // { value: undefined, done: true }
Calling generator.next()
repeatedly after our last statement above will only return
(or more accurately, yield
) the same return
object: { value: undefined, done: true }
.
Generators in Action
Looping through an Array:
Using a for of
loop we can iterate over our generator and yield
the content at each loop.
// create an array of animals
const animalsList = ['Cat', 'Dog', 'Monkey', 'Bird', 'Fish'];
// create our looping generator
function* loop(arr) {
for (const item of arr) {
yield `I like a ${item} as a pet`;
}
}
const animalGenerator = loop(animalsList);
console.log(animalGenerator.next());
// Object { value: "I like a Cat as a pet", done: false }
console.log(animalGenerator.next());
// Object { value: "I like a Dog as a pet", done: false }
console.log(animalGenerator.next().value);
// "I like a Monkey as a pet"
Our generator will now loop over the array and print one value at a time every time we call .next()
, To get only the value, then use .next().value
and it will not print the status of the generator.
.return()
in Generators
With .return()
we can return a given value and finish the generator.
function* animalsList(){
yield 'Cat';
yield 'Dog';
yield 'Monkey';
}
const animals = animalsList();
console.log(animals.return());
// Object { value: undefined, done: true }
We got value: undefined
because we did not pass anything in the return()
.
Summary
It’s not often you need generators. This article is just to provide a basic explanation of javascript generators. There is much more you can do with a generator, You can check out the official MDN documentation for more advanced cases where the use of generators can come in handy.
Top comments (5)
This is a very useful tutorial, but you really need to proof read your writing:
This is wrong. Your console should read:
And also this:
Is wrong. It should be:
Ohh Gutted to have totally missed that...
Thank you very much for your observations ad feedback I really appreciate them.
No worries. As I said, a great tutorial. 🙏
Nice thank you.
Give an eye here : DemoGen
Regards
I think, there is no full image of Generator usage if we miss passing to yield arguments. I mean we can pass to some value
generator.next('hello')
and get it body of the function viayield
keyword.-->