JavaScript Generators Simplified

Pro Members Only

This lesson is available if you have an active subscription.

Alternatively, some member might be able to gift it to you.

If you already have a subscription, you can sign in.

Professional Modern JavaScript Lessons

1.Course Intro
free
⏱️ 1:13
2.Setup & Tooling
free
⏱️ 3:32
3.Debugger Statements and Breakpoints
free
⏱️ 2:17
4.Primitive Data Types and Values
free
⏱️ 3:06
5.JavaScript Variables - let and const
free
⏱️ 4:50
6.Comments in JavaScript
free
⏱️ 2:55
7.JavaScript Identifer Naming
free
⏱️ 2:52
8.Using TypeScript
free
⏱️ 4:26
9.JavaScript String Masterclass
free
⏱️ 9:29
10.JavaScript Boolean Type
⏱️ 6:45
11.Missing Guide to JavaScript Numbers
⏱️ 15:28
12.JavaScript Objects Demystified
⏱️ 13:33
13.Functions in JavaScript
⏱️ 20:25
14.JavaScript Arrays Masterclass
⏱️ 22:31
15.JavaScript If Else Statements and Best Practices
⏱️ 6:13
16.JavaScript Conditional Expressions
⏱️ 8:38
17.JavaScript Loose vs Strict Equality
⏱️ 4:02
18.Truthy vs Falsy in JavaScript
⏱️ 3:44
19.Concept of JavaScript Nullish and Unification
⏱️ 5:51
20.JavaScript Classes - Object Oriented Programming
⏱️ 10:30
21.JavaScript Error Handling and Exceptions
⏱️ 13:21
22.JavaScript Nullish Operators
⏱️ 5:48
23.JavaScript Switch Statement Masterclass
⏱️ 8:07
24.JavaScript For Loop Iteration Simplified
⏱️ 10:59
25.JSON Masterclass
⏱️ 7:59
26.JavaScript While and Do While Loops
⏱️ 2:52
27.JavaScript Date and Time Simplified
⏱️ 13:16
28.this in JavaScript
⏱️ 12:04
29.JavaScript Tagged Templates Masterclass
⏱️ 5:48
30.Promises in JavaScript
⏱️ 10:01
31.JavaScript Async Await Masterclass
⏱️ 9:00
32.JavaScript Symbols Demystified
⏱️ 7:25
33.JavaScript Iterators and Iterables
⏱️ 8:50
34.JavaScript Generators Simplified
⏱️ 9:17
35.JavaScript Prototype - The Secret Guide
⏱️ 11:21
36.JavaScript Set Builtin Data Structure
⏱️ 9:52
37.JavaScript Map Builtin - HashMap Magic
⏱️ 10:38
38.JavaScript Deferred Promise Pattern - withResolvers
⏱️ 3:35
39.Cloning and Deep Copying in JavaScript
⏱️ 3:14
40.JavaScript Async Await Sequencing and Execution Masterclass
⏱️ 10:31
41.JavaScript Memory Management Masterclass
⏱️ 5:26
42.JavaScript WeakMap Demystified
⏱️ 8:58
43.JavaScript bigint Masterclass
⏱️ 5:35
44.JavaScript WeakSet Explained with Examples
⏱️ 7:47
45.JavaScript Regular Expressions Masterclass
⏱️ 17:54
46.JavaScript Weak References Demystified
⏱️ 5:29
47.JavaScript Memory Leaks Demonstrations and Fixes
⏱️ 6:01
48.Semicolon Free Coding in JavaScript
⏱️ 3:46
49.JavaScript Modules Masterclass
⏱️ 11:36

JavaScript Generators Simplified

Subscription Required

You must have an active subscription to access this content.
If you already have a subscription, you can sign in.

Generators, Iterators and Iterables

// Generator
function* simple() {
yield 1;
yield 2;
yield 3;
}

// Iterator
const iterator = simple();
console.log(typeof iterator.next); // function

console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: undefined, done: true }

// Iterable
const iterable = simple();
console.log(typeof iterable[Symbol.iterator]); // function

for (const value of iterable) {
console.log(value); // 1 2 3
}

Order of Execution

function* simple() {
console.log('starting');
yield 1;
console.log('resuming');
yield 2;
console.log('complete');
}

const result = simple();

console.log(result.next());
// starting
// { value: 1, done: false }
console.log(result.next());
// resuming
// { value: 2, done: false }
console.log(result.next());
// complete
// { value: undefined, done: true }

Real World Example

function* range(start = 0, end = Infinity, step = 1) {
for (let i = start; i <= end; i += step) {
yield i;
}
}

const iterator = range(0, 2);
console.log(iterator.next()); // { value: 0, done: false }
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: undefined, done: true }

for (const value of range(0,2)) {
console.log(value); // 0, 1, 2
}

const values = [...range(0, 2)];
console.log(values); // [0, 1, 2]

Lazy Evaluation

// 0,1,2,3,...
function* whole() {
let start = 0;
while (true) {
yield start++;
}
}

for (const number of whole()) {
console.log(number);
if (number === 100_000) break;
}

Early Exist

class CancellationToken {
isCancelled = false;
}

function* iterate(maxValue, token) {
let i = 1;
while (i <= maxValue) {
yield i++;
if (token.isCancelled) {
return;
}
}
}

const token = new CancellationToken();
for (const value of iterate(10, token)) {
if (value % 5 === 0) token.isCancelled = true;
console.log(value); // 1, 2, 3, 4, 5
}

Generator Methods

function* simple() { yield 'a'; yield 'b'; }
console.log([...simple()]); // ['a', 'b']

const object = {
*simple() { yield 'a'; yield 'b'; },
};
console.log([...object.simple()]); // ['a', 'b']

class Class {
*simple() { yield 'a'; yield 'b'; }
}
console.log([...new Class().simple()]); // ['a', 'b']

class Fancy {
*[Symbol.iterator]() { yield 'a'; yield 'b'; }
}
console.log([...new Fancy()]); // ['a', 'b']

yield*

function* oneTwo() {
yield 1;
yield 2;
}

function* fancy() {
yield* oneTwo();
yield 3;
yield 4;
yield* [5, 6];
}

for (const value of fancy()) {
console.log(value); // 1, 2, 3, 4, 5, 6
}
javascript
typescript
react
playwright

Enjoy free content straight from your inbox 💌

No spam, unsubscribe at any time.

Transcript

00:00

JavaScript generators make it super easy to create intervals with special syntax for defining the generator using function star and returning individual values with yield. Hey, we are defining a generator called simple and what makes it a generator instead of just another function is the fact that we are using Function Star. With STAR is also called the aesthetics character. A generator is essentially a function that can be paused every time we return a value. And the way we return a value is with a yield keyword. So when someone asks this function for values, it'll first give back the numeric value of one and then essentially pause the function execution. Execution will resume with the next values requested.

00:37

And hey, we are going to yield two. Then execution will again pause, and when the next value is requested, execution will resume and people will yield the value of three. And then again the execution will pause. And when the next time the value is requested, as we do not have any more statements, the generator will then terminate you invoke the generator like a standard function and it gives back a generator object. An individual generator object essentially controls the particular execution of the generator function. The generator object actually follows the iterator protocol that we've looked at in a previous lesson. And what that means is that it has a next member,

01:10

which is of a type function, and we can actually get the individual values back from the generator by invoking next. Every single time we need a new value. Each invocation of next gives us back a result that has a value. And of course the first value that we are yielding here is one. So value is going to be one along with a done bullion, which will be false as long as there are more statements to execute within the generator. So for our particular generator, if we invoke next, again, we get back the value two done falses, we invoke it again, we get back the value three done falses, and now the generator execution has completed. So we get back the value.

01:44

Undefined and done. True. The main use case for the generator is not the fact that it follows the iterator protocol. It is the fact that it follows the Iterable protocol. So let's invoke the generator again in this time store the generator object that is returned into a variable called Iterable. And as we saw in a previous lesson, we can actually prove that it is an Iterable because it has a wellknown property symbol iterator, which is of type function. We've seen how JavaScript has special syntax for using intervals. For example, we can use them with the JavaScript four off. And of course if you four off on this particular generator object,

02:18

we get back the values that we saw before, which is one, two, and then three. So to recap, we invoke the generator like a standard function, but instead of giving back a result, it gives back a generator object. And this object is both an iterator and it is iterable. And most commonly you would use it as an iterable. With generators, it's really important to understand how the order of execution works. So let's add some logs to monitor everything that we can about the generator. We create a simple generator and add a log statement before and after every yield statement. When we invoke the generator, we immediately get back a generator object and the execution of the generator

02:54

body actually doesn't start. Only when a value is requested does the generator start executing. So at this point we will see the starting log as well as the value that will be returned after the first yield call, which is value one done false. And again, the generator will be paused and only when we request the next value does it resume and yield the next value. And again, it pauses and only when we request the next value does the execution resume and we have a simple console log complete at which point all the statements within the generator have been executed and it simply returns back the value undefined done. True generators greatly simplify real world handling of intervals.

03:31

And just like with async awai, which really makes promise based code look like simple synchronous code with generators, we sort of don't have to constantly think about the underlying concept of iterators and itals. You might recall this code from a lesson on iterators and Iterable, and I won't even bother explaining it again because we can actually do it much more simply by using generators. So here we are defining a generator called range that takes a start value and end value and a step size. And we need to generate values that start at start and at end each time getting incremented by the step size.

04:04

We can do that with a very simple fall loop and in each iteration simply yield back the current value of the loop variable I we can use the result of the generator as a simple iterator by working next and getting the individual values. So for range zero to two we get 0 1 2 and then done becomes true and even more efficiently by using it as an iterable with a simple four off loop or even convert this range into an array by simply using the spread operator that as we saw also works on top of intervals. This example really demonstrates the beauty of generators and how the gritty simplify creating our own intervals.

04:39

The real advantage of creating an iterable result over a standard JW skip array is that an iterable allows lazy on-demand return of individual values. As an example, if you wanted to generate all of the whole numbers, of course they're unbounded on the top side and we couldn't do this with a standard JavaScript array, but we can still iterate over them by simply using a generator. And now we can loop over whole numbers using a simple four off loop. And of course we don't want to do this for infinity, so I will still add a break statement if the number becomes a hundred thousand. As we've seen,

05:13

we normally return a value back from the generator by using the yield keyword, but you can also use an empty return statement within this generator whenever you want to directly move the iteration into the done state. For example, we can create a class called cancellation token, which has a simple bullion property is canceled, which we initialize to false. We will utilize this cancellation token if you ever want to stop executing a particular generator. We create a simple generator called iterate that takes a max value and a cancellation token starts off with I equal to one and then starts incrementing I returning the values individually till I is no longer,

05:48

less than or equal to max value. Within the loop, we also check the cancellation token and if it has been canceled, then we will early terminate the generator by using a return statement To demonstrate how this return statement will work, we create a new cancellation token and start iterating a ax value of 10 by using this cancellation token. If at any point the value becomes divisible by five, we will cancel the token by setting its is canceled ion to two. And then for the rest of the loop, we will simply log out the current value that got generated. The generator is designed to generate values one to 10, but since we cancel at five,

06:22

that is the last value that we will see behind the scenes. The return statement is essentially turning the iterators done bullion to be true in addition to standalone function star declarations that we've been looking at. JavaScript generators can also be defined as methods of objects and classes by simply prefixing the member with a star character to set us up for success, consider a very simple generator which yields two values, the string A and the string B, and we can invoke it pretty much like a standard function. It gives back an and we can spread it into an array. If you wanted to to convert the methadone and object into a generator,

06:56

we simply prefix the name of the method with the star character and this turns that method into a generator, which means that we can yield values. For example, A and B. This star does not become a part of the method name. So to use it, we simply invoke it using the generator name, which is just simple. And of course we can iterate over it to turn it into an array. If you wanted to. Converting a class method into a generator is exactly the same, you simply prefix it with a star. And of course invoking it gives us a generator object, which is both an iterator and is iterable. We can even prefix computed members with a star to turn them into a generator.

07:31

So let's do something really cool. Define a computed property using the well-known symbol iterator. And of course, since it is a generator, it's going to return an object, which is going to be an iterator, and therefore instances of the class fancy itself will become iterable because they will follow the iterable protocol, which we looked at in a previous lesson. This is really useful when you are building your own data collection classes and want to support something like four off. And in terms of behavior, all of these generators yield the values A and B, and that is what we see in the program output. In addition to the yield operator, which returns a single value,

08:04

generators allow you to queue the return of entire intervals simply by using the yield star operator. Here we have a very simple generator called a one two, which yields the values of a one and then two. Now let's create another generator that we will call fancy and use the yield star operator. The yield star operator works with Iterable, and as we know, calling a generator returns an interval and a yield star basically yields those values one by one. So for our call to one, two yield star will first yield one and then yield two. And of course, we can yield star from any generator just like we can yield from any generator.

08:40

And one thing worth pointing out is that a set that yield star works with iterable, which means that we can use any iterable, even the JavaScript builtin array if you wanted to. So if you iterate over the result of fancy using a simple four off loop, you will see the values from one two, which Is one, two, then three, then four, and then the values from five six, which is five and six. If I had to rank the coolest features of transcript, it would be a close match between async await and generators. In terms of utility async, AWAI would win. But in terms of geeking out generators are pretty awesome. I hope you enjoyed this tutorial. As always,

09:13

thank you for joining me and I will see you in the next one.

Professional Modern JavaScript

Professional Modern JavaScript

1.Course Intro
free
⏱️ 1:13
2.Setup & Tooling
free
⏱️ 3:32
3.Debugger Statements and Breakpoints
free
⏱️ 2:17
4.Primitive Data Types and Values
free
⏱️ 3:06
5.JavaScript Variables - let and const
free
⏱️ 4:50
6.Comments in JavaScript
free
⏱️ 2:55
7.JavaScript Identifer Naming
free
⏱️ 2:52
8.Using TypeScript
free
⏱️ 4:26
9.JavaScript String Masterclass
free
⏱️ 9:29
10.JavaScript Boolean Type
⏱️ 6:45
11.Missing Guide to JavaScript Numbers
⏱️ 15:28
12.JavaScript Objects Demystified
⏱️ 13:33
13.Functions in JavaScript
⏱️ 20:25
14.JavaScript Arrays Masterclass
⏱️ 22:31
15.JavaScript If Else Statements and Best Practices
⏱️ 6:13
16.JavaScript Conditional Expressions
⏱️ 8:38
17.JavaScript Loose vs Strict Equality
⏱️ 4:02
18.Truthy vs Falsy in JavaScript
⏱️ 3:44
19.Concept of JavaScript Nullish and Unification
⏱️ 5:51
20.JavaScript Classes - Object Oriented Programming
⏱️ 10:30
21.JavaScript Error Handling and Exceptions
⏱️ 13:21
22.JavaScript Nullish Operators
⏱️ 5:48
23.JavaScript Switch Statement Masterclass
⏱️ 8:07
24.JavaScript For Loop Iteration Simplified
⏱️ 10:59
25.JSON Masterclass
⏱️ 7:59
26.JavaScript While and Do While Loops
⏱️ 2:52
27.JavaScript Date and Time Simplified
⏱️ 13:16
28.this in JavaScript
⏱️ 12:04
29.JavaScript Tagged Templates Masterclass
⏱️ 5:48
30.Promises in JavaScript
⏱️ 10:01
31.JavaScript Async Await Masterclass
⏱️ 9:00
32.JavaScript Symbols Demystified
⏱️ 7:25
33.JavaScript Iterators and Iterables
⏱️ 8:50
34.JavaScript Generators Simplified
⏱️ 9:17
35.JavaScript Prototype - The Secret Guide
⏱️ 11:21
36.JavaScript Set Builtin Data Structure
⏱️ 9:52
37.JavaScript Map Builtin - HashMap Magic
⏱️ 10:38
38.JavaScript Deferred Promise Pattern - withResolvers
⏱️ 3:35
39.Cloning and Deep Copying in JavaScript
⏱️ 3:14
40.JavaScript Async Await Sequencing and Execution Masterclass
⏱️ 10:31
41.JavaScript Memory Management Masterclass
⏱️ 5:26
42.JavaScript WeakMap Demystified
⏱️ 8:58
43.JavaScript bigint Masterclass
⏱️ 5:35
44.JavaScript WeakSet Explained with Examples
⏱️ 7:47
45.JavaScript Regular Expressions Masterclass
⏱️ 17:54
46.JavaScript Weak References Demystified
⏱️ 5:29
47.JavaScript Memory Leaks Demonstrations and Fixes
⏱️ 6:01
48.Semicolon Free Coding in JavaScript
⏱️ 3:46
49.JavaScript Modules Masterclass
⏱️ 11:36