Transcript from the "Generator Functions" Lesson
>> Steve Kinney: Talk about generator functions, right? Generator functions are, I believe in the ES6 pack, ES2015, and effectively they're a way to delay execution. Normally we say functions run to completion. When you call a function, it does everything until it either hits a return statement, throws an arrow that you didn't catch, or reaches the end.
[00:00:43] A lot of that is provided by the web APIs, like XML HTTP request or by Node.js, right? The language itself is no more asynchronous than Ruby is, or PHP, or anything along those lines. So generators give us a way to stop, wait until it's time to start again.
[00:01:04] And go do the next thing, which is really helpful sometimes for dealing with asynchronous code. So here's a part of the promise of the ES6 spec was that you should never have to write function again. But this is one example where there isn't an arrow function syntax for it.
[00:01:19] I don't really care, but I know some people care very deeply about this. And you'll notice that it's just got a little star next to it, and that's what makes it a generator function, you can think of it as a superstar. Fun fact about the star, the star can go next to the function.
[00:01:37] It can go next to the function name. It just can't float in the middle. It has to be globbed on to one of those two identifiers. It just can't sit with a space on each side. So we can all have a long argument later on which syntax we all like, but this is the one I've gone with.
[00:01:53] So, we look at this, generate three numbers. We yield 1, we yield 2, we yield 3, that's kind of interesting.
>> Steve Kinney: And then we can effectively think about it instantiating a new generator, right? If we call it, we get back a generator. We can say .next, you get yield 1 and done being false.
[00:02:12] You call .next again, you get 2. And still not done, you call next, you get 3. But then, you've hit the end of the function and you're done. But, the important part is once you've yielded 1, it kind of stopped in between lines 2 and 3. It just paused, it didn't run to completion.
[00:02:29] It didn't follow until it hit a return statement, or threw an error, or anything like that. It just, hey, I'll just sit here half done. You let me know when you want me to continue. And so this is going to become a slightly powerful idea when we think about I haven't heard back from the network yet, why don't you wait here.
[00:02:46] Cool, so the interesting thing that most people don't know about generators is that you can actually pass in more data, even while they're paused. So we'll have this one called addNumbersEventually. And it will take a, and then you see how on line 2 it yields a? It will give you back a, but when you call next, you can pass in a value that will be given to b, and then eventually you can add a + b.
[00:03:13] So we have a, we yield a back out to whatever, call it .next. And when they pass in, when they call .next they can pass in b and then we'll have both of them. So we can add numbers eventually. We'll say .next is 2, so it gave us back 1.
[00:03:27] It took in the 2 and then we called it again. We yield 3, or return 3 rather. So this is kinda cool, so we can pause things, all right, we can have a thing, we can wait. We can also actually pick up back where you left off. I have more information for you, right?
[00:03:45] Hopefully async is ringing in your mind at this point of hey, I need to get some information from the server, chill. Okay, guess what, we got the information from the server, pick up where you left off, right? And you might use generators more than you think without ever typing the generator, right, and we'll talk about that in a second.
[00:04:05] So we have the ability to pause functions, and come back later with more information. This seems like we could do something clever here, and escape a lot of the asynchronous patterns. So this is very contrived, but here I have a generator function. I've called it main and I wanna get my GitHub profile and my buddy Lon's GitHub profile.
[00:04:27] Those are two network requests. I don't wanna go into callback hell here, where I have to fetch the first one. And then have another callback fetch the second one, or fetch both of them, but have a gate to make sure I get both, right? Yes, I could use promise.all, totally, but still even that if one of them fails and not the other, it's just a mess, right?
[00:04:47] Here I can yield the first one, wait, go get the second one. You can see that we have a generator. We start it up on line 12 by calling it. And we kick it off on line 13 by saying next. It waits until we make the Ajax request.
[00:05:04] That promise resolves on line 2, and hold on, I gotta highlight this for you. All right, we can yield, when that promise resolves on line 2, it kicks it back off again, and we can go to the next line. And so we have a way to pause, until we hear back from the network and move on to the next thing.
[00:05:24] If part of you is like, hey, this reminds me of async await. That's because async await is basically syntactic sugar on this, right? It reminds you of async await, cuz effectively it's a much uglier version of async await. But that is generators and that's what generators bring to the table in this case.