Bummer! This is just a preview. You need to be signed in with a Pro account to view the entire video.
Start a free Basic trial
to watch this video
Reaching asynchronous cloud nine in JavaScript
16:56 with Garrett JohnsonAsynchronous code can be tough to manage, even for a seasoned JavaScript developer. Sometimes it seems like the only options are a pyramid nested callbacks, a pyramid of nested promises, or trying some functional tricks that your friend Monad told you about in math class. Well, thanks to one of the language enhancements in ES6, we have a new option: clear and concise code with generators
-
0:00
[MUSIC]
-
0:06
So we're gonna talk about reaching asynchronous cloud nine in
-
0:10
JavaScript with generators,
-
0:12
which is basically a fancy way of saying we're gonna make JavaScript not suck.
-
0:17
The first one thing real quick.
-
0:20
I work for a company called Segment.io, and
-
0:23
if you want a really cool shirt like the one I have on, or
-
0:26
a really cool sticker like that, you can come grab one afterwards.
-
0:30
So asynchronous programming really sucks sometimes.
-
0:37
Sometimes it feels like juggling all these call backs,
-
0:40
feels a lot like this guy here trying to throw a boomerang.
-
0:44
You know, cuz you, you have to just pass values and
-
0:48
pass behaviors around, and you end up with just, you know, a small example.
-
0:52
You end up with code that looks like that and it's it's not fun to maintain at all.
-
0:57
I don't know about you guys, but
-
0:59
I get kinda irritated with it cuz when you go to change things,
-
1:03
you end up doing things like that when you try to re-factor your application.
-
1:09
And it's just it's a pain.
-
1:11
[BLANK_AUDIO]
-
1:14
And you're supposed to kinda, people say they're gonna fix it with promises but,
-
1:19
you know, we could see this application with promises.
-
1:22
It's just a pyramid of promises instead of callbacks.
-
1:27
And that kinda sucks too.
-
1:30
And, when you kinda put this all together, you're like doing this this,
-
1:34
this balancing act of all this coordination, right?
-
1:37
And it just seems like it's a lot harder than it has to be.
-
1:40
And I, I started finding myself frustrated, cuz you seem like you're,
-
1:44
instead of focusing on your business problem, that you're trying to solve,
-
1:48
you've now created this code problem.
-
1:50
And you're like spending all day trying to figure out what needs to be synchronise,
-
1:54
what needs to be sequential.
-
1:55
And now you're solving that problem instead of what you get paid to solve.
-
1:59
And that's just irritating.
-
2:02
And you end up just wanting to smash your keyboard against your computer.
-
2:07
So thankfully, there is a better way.
-
2:12
And that's with generators,
-
2:14
which is in the new what they call ECMAScript 6 addition to JavaScript.
-
2:20
Which is kinda the new features that are slowly being rolled out.
-
2:24
The ironic thing, is generators aren't really meant for
-
2:27
asynchronous programming at all.
-
2:29
And we're just gonna make them work anyways.
-
2:33
And there's a lot of framework's built around them and
-
2:35
everybody's kinda jumping on board.
-
2:37
Cuz they're there and we're gonna make it work, kinda like this kid with his toys.
-
2:43
So in a sense, they're not really meant for asynchronous control flow.
-
2:51
We're gonna kinda go over some of the basics of
-
2:53
how you can make them work to your advantage.
-
2:56
And then you'll kinda understand some of these new tools in the node
-
3:00
community at least.
-
3:01
That's kinda where I focus like co and coa and how they actually work, and
-
3:05
how you can kinda leverage those in the future.
-
3:07
[BLANK_AUDIO]
-
3:10
And by the way, if you have any questions.
-
3:12
If you can kinda just interrupt me.
-
3:14
So, no biggie.
-
3:16
I'm gonna kind of assume you have some JavaScript knowledge.
-
3:20
Most of this stuff, it can work with node or
-
3:23
in the browser, assuming it's a modern browser.
-
3:27
But we're gonna talk about some of the tools you can do to get around that.
-
3:29
[BLANK_AUDIO]
-
3:32
So, a generator.
-
3:36
The basic generator looks like your normal function,
-
3:40
except you have this little asterisk, asterisk at the top on the name and
-
3:45
then we have this new keyworld, keyword called yield.
-
3:50
And other than that they look the same.
-
3:52
Just have some new syntax.
-
3:54
When you invoke it, you can just assign it to a variable.
-
3:58
And then you have this new method called next.
-
4:01
[BLANK_AUDIO]
-
4:05
And as you call next you get values back.
-
4:10
And it's an object with a value property and a done property.
-
4:15
And the value property is gonna be whatever you yield.
-
4:19
So in this example, we yield three times so as we run it,
-
4:24
we get one, two, three and then the last one is undefined.
-
4:29
However you'll notice done is true now.
-
4:33
So if you've ever used iterators before in
-
4:36
another language it's actually built on top of iterators.
-
4:39
It's just kind of, there's some magic going on behind the scene where yield and
-
4:43
next, are able to coordinate iteration.
-
4:50
So not only can you send values back, you can also send values into the generator.
-
4:57
So here same exact thing except now we're yielding and
-
5:02
then we're getting a value back from yields.
-
5:05
So basically, what we see here is,
-
5:10
when you first create the generator, the very first time,
-
5:13
you call it next, you, you wake up the generator out of its suspended state.
-
5:18
Cuz when you first create it, nothing happens.
-
5:20
So if we didn't call it dot next on that first line or below you have no output.
-
5:30
However, the first time we call it we'll get here and
-
5:34
then we'll get that value done and one, and then it would stop.
-
5:37
But since we call it again,
-
5:39
we get the value a received back out of the yield, cuz it basically freezes.
-
5:47
Up to right after the yield and it goes back into
-
5:55
suspended state.
-
6:02
[INAUDIBLE]
-
6:09
No, because your first iteration's going to take it up to the yield and then right
-
6:14
before the assignment happens, it's going to go back and this has been its state.
-
6:17
And that next call, it's going to take the value that you're passing in next, and
-
6:22
it's going to have it and it's going to go to the next yield stop.
-
6:25
And then the next one.
-
6:27
>> So that's just [INAUDIBLE] >> Yes, yeah, yeah.
-
6:32
>> [INAUDIBLE] >> And
-
6:40
we're gonna go over the ascending values pretty quick cuz as we get into
-
6:44
the asynchronous programming,
-
6:46
there's not a whole lot that we're gonna do with it for our example.
-
6:50
So what the third really interesting thing with
-
6:54
generators is it also has a throw method on the generator.
-
7:00
And you can throw an error inside of the generator.
-
7:05
So in this example we're gonna iterate up to the first time.
-
7:10
And then we're gonna throw an error and you can see here
-
7:18
that we got our first iteration now, but then we get an exception thrown.
-
7:25
And you'll have to trust me because I don't want to go back and forth
-
7:28
between the code editor, but stack trace actually lines up to where the yield was.
-
7:35
Which is pretty nice, cause then we can actually put a try catch
-
7:41
inside of our generator, and we can try and yield something and if something thr,
-
7:46
uses our generator throw we can actually catch what they're throwing.
-
7:51
Mean, you have to put that in the back of your mind.
-
7:54
For now 'till we get back to how we can use that for asynchronous programming.
-
7:59
What you're probably wondering by now, you know, WTF,
-
8:02
what does this have to do with asynchronous programming?
-
8:05
You're talking about iteration and generators.
-
8:08
however, if we look back at some of the basics of asynchronous programming and
-
8:14
then kind of JavaScript.
-
8:16
We'll be able to draw some pretty close parallels.
-
8:20
And if you understand those basics,
-
8:24
then you can apply generators without a problem.
-
8:29
So here, we have kind of a simple problem, just three functions.
-
8:37
That just do kind of a set timeout and logging.
-
8:40
I didn't want to go complicated with, databases and
-
8:43
all that, so, just a simple problem.
-
8:45
But then in the bottom here we're just gonna call them in row.
-
8:48
One, two, three, console log.
-
8:50
And does anybody wanna guess what the output of that's gonna be?
-
8:57
Yes, so it's not in order right?
-
8:59
Cuz it's asynchronous.
-
9:02
Yeah it was a, sorry if you couldn't hear, it was done two, three, one.
-
9:08
So, and that's because everything's asynchronous so
-
9:11
in order to have sequential order what do we use in JavaScript to,
-
9:14
be able to call something and then call the next thing the next thing right?
-
9:18
You have to use callbacks or promises or, you know, some variation.
-
9:27
So we go back to our three functions.
-
9:29
And we have to add a callback to each of em.
-
9:32
And it's all pretty simple.
-
9:35
You just gotta pass in the function as a value and then we'll just invoke it.
-
9:39
And then a horrible way to use it, would just be, you nest it, and that's how
-
9:44
end up with the whole call [INAUDIBLE] stuff.
-
9:49
We just call each one, and then we pass the, a callback function,
-
9:52
which'll call the next one and the next one and the next one.
-
9:55
Which is kind of probably the way you wrote code the very first time you
-
10:00
tried to write an asynchronous app.
-
10:03
But then, there's tricks to make that not so nested and
-
10:06
crazy and these are the tricks that some of the libraries like async use but
-
10:11
they handle a lot more cases.
-
10:14
Cuz what we wanna do is basically take three functions and
-
10:17
run them in a row, right?
-
10:18
And now that we've added a call-back,
-
10:21
we can just have a utility function that can do that for us.
-
10:25
So, if we skip the top function but look how we're gonna use it.
-
10:29
We just have this run function and
-
10:31
we're gonna pass it, this array of three functions?
-
10:36
And what that utility is gonna do is call those in order, and
-
10:40
it's gonna have this internal next function that just
-
10:45
recursively calls the next one until there's no more functions left.
-
10:53
And when there's no more left it just calls our done function for us so
-
10:58
we can do something afterwards.
-
11:00
Pretty straightforward, right, make sense?
-
11:03
So if you're kinda thinking, like wow, this whole iteration until you're done,
-
11:08
that kinda sounds similar to what you, we just talked about with generators.
-
11:14
And if you thought that before I said it, you're awesome.
-
11:17
If not, we'll get there.
-
11:20
And we'll talk about how we can make it work.
-
11:25
So, we can just change our
-
11:30
run function to, utilize what we just learned about generators, and
-
11:35
apply the very similar concept but instead just,
-
11:40
instead of popping off functions from the stack, just call generator.next.
-
11:48
And we just learn with the next,
-
11:51
it just takes, the value that gets sent back from yield.
-
11:57
Now, with yield, you can yield anything.
-
12:00
So what we're gonna do is we're gonna yield functions, and then our utility
-
12:04
function's gonna grab that function that's been yielded to it and call it.
-
12:09
And then do that same recursive trick,
-
12:12
where it just passes itself, to that callback.
-
12:16
[BLANK_AUDIO]
-
12:24
And then soon as it's done, we'll just call the done function.
-
12:26
Or just return, actually cuz we don't have to call [UNKNOWN]
-
12:31
[BLANK_AUDIO]
-
12:37
So, again. If you're thinking you can yield anything,
-
12:41
you're correct.
-
12:42
We can yield, other generators.
-
12:45
We can yield objects or arrays.
-
12:46
We can really yield anything I think, except for an undefined value.
-
12:51
[BLANK_AUDIO]
-
12:58
So, doing that's a little more complicated.
-
13:02
So we're actually not going to write that in our done function.
-
13:05
There is libraries that are built by really smart people that have done that.
-
13:10
And one is called co.
-
13:12
Which does basically, what we just did.
-
13:16
and, here's an example of it being used so this is node by the way so, it's
-
13:22
a node module, so you just require it, and you pass in your generator function.
-
13:28
And it will run it for you.
-
13:32
And figure out all the yields.
-
13:34
And do the sequential or
-
13:37
parallel processing based on the values you give it.
-
13:41
but, and this is a simple example.
-
13:43
Rather than our callback one, two, three, we're actually, wrote those as generators.
-
13:48
And we passed the generator to yield.
-
13:52
And co-resolves that for us.
-
13:55
So in the first one after it's created we do the yield sleep.
-
14:00
Well what sleep does, is it just returns a function that accepts a function.
-
14:04
That after set, a certain set time out it continues.
-
14:08
Inco will traverse that and then once it's done will move on to the next one.
-
14:13
And just does the whole next iterator dependency tree all
-
14:17
the way down until there's nothing to next.
-
14:19
So we'll look at some
-
14:24
more kinda more advanced examples of what you can do with it on their on their site.
-
14:30
But before I forget.
-
14:33
Other tooling so all these can be used in node 11 or above.
-
14:39
I think it's node 11 3.
-
14:41
But the current version is 11 13 which it says unstable, but
-
14:45
we use it in production and it works great.
-
14:48
And you have to pass this harmony flag to it since that's part of the es 6 and
-
14:52
that's how you turn it on.
-
14:55
And the latest version of Chrome has em.
-
14:57
And the latest version of Firefox.
-
15:00
And then if you need to work with older browsers,
-
15:03
there's this really neat tool called Regenerator.
-
15:07
And I just spelled generator.
-
15:08
Sorry I misspelled that.
-
15:10
But Facebook built this tool that basically will compile your generators,
-
15:16
using it's a node module called [INAUDIBLE].
-
15:19
So it takes the syntax tree of the generators and
-
15:22
then rewrites it as callback functions, and then just dumps it out.
-
15:26
So you can compile a really nice-looking app for all the browsers.
-
15:35
But along the lines of tooling.
-
15:37
[BLANK_AUDIO]
-
15:40
Where's the object example.
-
15:44
Down here.
-
15:44
[BLANK_AUDIO]
-
15:54
Yeah, so you can yield objects or erase.
-
15:58
And code will traverse the object and inspect every property.
-
16:02
And call those for you.
-
16:04
So, if you just want to create like an instance of a,
-
16:06
you know, a class in JavaScript.
-
16:09
And just have all your methods that you want to be called.
-
16:12
It will figure that out for you.
-
16:16
And a raise will be iterated in parallel, so
-
16:18
if you have like an array of a bunch of requests you want to make,
-
16:22
you can just yield that array of all the outgrown requests, and
-
16:26
it resolve each one and after the last one is done, it will continue on.
-
16:30
[BLANK_AUDIO]
-
16:43
Get back into presentation right.
-
16:47
All right. [BLANK_AUDIO]
-
16:50
So, any questions?
-
16:52
I kind of flew through that really quick, quicker than I thought I would, so.
-
16:56
Go for it.
You need to sign up for Treehouse in order to download course files.
Sign up