This course has been updated! We now recommend you take the Introduction to Node.js, v3 course.
Transcript from the "Asynchronous Patterns" Lesson
>> Speaker 1: And I just wanna talk about some async patterns here. So again, you've probably done async in node before, I'm sorry, in browser, but this is a little bit about it in node. TLDR, async await is legit. Like, use async await. Just use it, it's legit. Have it in a browser now, I'm pretty sure.
[00:00:17] Just use it, it's amazing. If you don't know what it is, that's all right, you're gonna use it today [LAUGH] and I'm gonna tell you about it. But first one is the callback pattern, and, yeah, you probably know about callbacks, but in node, there's a specific callback pattern.
[00:00:30] And basically, whenever you do something in async, the callback function takes two arguments. The first argument is always the error, if there's an error. It'll be null if it's not. And the second argument is always the result of the callback action, if there's a result. Or null if it's not.
[00:00:42] And that's literally every callback ever in node. And there's no standard for that, it's just something that the community adopted and that all the node internal modules use. There's no rules for that, that's just how it is. So like I said, it's not all bad. Everybody in the community's not jerks, [LAUGH] they'll form to patterns and do things.
[00:01:02] So yeah, this is the pattern if you use callbacks, but this is kind of yesterday. Nobody really even uses callbacks, anymore. I can't stand to use a callback ever again, so I just don't even use them. If you try to submit a PR with a callback, I'll just be like, no, just get it out of here.
[00:01:17] But if you were to do callbacks, this is it. This is how you would do it. Error first, result second. Know if either one of those are node. Promises, the next step up. So promises is your AsyncThing return's a promise, which you can call .then on or .catch.
[00:01:35] So this allows you to, yeah, basically it's just like a prettier version of a callback. At the end of the day it's still a callback, except for you have control over when it's resolved, versus being notified later when it comes. So it helps with your code, keep it cleaner.
[00:01:48] It gives you control over the flow versus you giving control over to the callee. So a promises are just a little better for that and you could do this in a browser too. Promises have been in browser for a very long time. It's a very standard things, so if you haven't done promises before.
[00:02:04] Yeah, you should totally be using promises, just use promises in the browser, they're not super complicated. But the next step up from that is a async/await. So async/await is taking your asynchronous code and making it synchronous. So basically the way you would do it as you would use the async keyword in front of a function.
[00:02:26] And then anything that was a promise, and it has to be a promise. So do async things still would have to be a promise here. You could put the await keyword in front of it, and then it won't move to the next line until that promise resolves. That's basically it.
[00:02:38] So it's just turning your asynchronous code into synchronous code, line by line. All you gotta do is just instrument the function with the async keyword and then await anything that's a promise. And you could do that anywhere. Anywhere in the async function, you can use await on a promise and it will await for it to come back.
[00:02:54] The problem of this introduces is now error handling. Whereas with a promise you could do .catch . With async/await If this throws an error, it's just gonna blow up and crash. It's gonna destroy everything, so now, you've got to figure out a different pattern to do that. So the obvious one is you use try catch, which is what you would normally do in asynchronous code, wrap something in a try, catch it in a catch.
[00:03:15] But a lot of people are using other patterns where, instead of returning a results here, or blowing up if there's an error, you'll just return an array. And the first thing in the array will be an error and the second thing in the array will be the results.
[00:03:26] A promise will not always resolve. Even if it errored, but the first argument in the array would be an error and the second one will be the result. So that's the way the community is moving towards. That's what we do in our code base. That way, you can explicitly handle your errors.
[00:03:40] That's just a really good way to do it, but, yeah, this is definitely what you wanna to do. It's pretty legit. Promises are pretty good too, in fact, you have to do it for async/await. And callbacks aren't bad, it's just callbacks, there's better things. So the callbacks get really nasty when you have callbacks in callbacks.
[00:04:01] In callbacks, in callbacks, right? And there's just like this pyramid, and it comes out like this, right? That's when they get really bad. So it's really hard to see how bad they are. In this example, they actually look probably cleaner, because this is like one line. But once you start doing like, I need to do this thing, then do these 10 things, then do this one thing, then callbacks are just like, nope, can't do it.
[00:04:21] Can't do it and then you need something like promises or async/await, where it's just like, this thing, 10 things, 1 thing, 5 things, done. That's async/await. So that's why you want that. Any questions on these async patterns? Yes.
>> Speaker 2: Does await make it be blocking? And therefore sort of synchronous, and therefore sort of ruins your node app, because your node app is sort of just sitting there secretly waiting for something on the server.
[00:04:49] Nobody else can hit that app now.
>> Speaker 1: That's a really good question, but no it doesn't. It's still asynchronous. It's basically the same as if, if you look at this console.log right here, right? If I were to put this console.log inside of this then block up here, it's still asynchronous.
[00:05:06] The console.log just didn't happen until the promise was done. That's the same thing that's happening here. It just looks like it's synchronous, so.
>> Speaker 3: This is like events, pretty much, right? Kind of event stuff?
>> Speaker 1: Yeah, it is event-based. It is mostly event-based, yeah, so, yeah, this looks like it's not going to the next line.
[00:05:24] But in reality is because this is inside of it a sync operation that you can imagine this being inside of a callback that's waiting on this to be done. That's what it is. It's like if I took this console.log and put it in this callback up here. That's what's happening.
[00:05:39] So every time you put in your weight over something you're basically making a call back you can think about it like that. So, it's confusing cuz it's on the next line, but it's really not, it's actually in the response of something happening later. So there was no blocking.
[00:05:52] So if I hit at API and it ran this function and another request came in, this isn't gonna stop that request from happening, it's still gonna do that request whereas if this was synchronous and it took 5 seconds, yeah, it's going to stop, it's gonna stop.
>> Speaker 4: What's the best way to group a bunch of asynchronous things?
[00:06:12] You know, some of the early jQuery promise patterns you could say, I want this to happen and then all of these things can happen, and then this one thing can happen, you know what I mean?
>> Speaker 1: Yeah, so, there's a lot of tools for that. At the end of the day you definitely want to use promises.
[00:06:26] So if you can make everything a promise, then you're good. So for instance, a group of things, you can use promise.all which takes an array of promises. And when all those resolve, then it will return one promise, right. Only when all those resolve. If you got 11 things and ten of them are done and the 11th was not, it's not gonna resolve.
[00:06:43] So it'll wait for all of them, and if one thing fails, it will fail. So promise.all is a really good control flow. So you can say, cool, wait for this promise, then wait for all ten of these inside this promise.all, then wait for this one, and then return the result of adding them together or something like that.
[00:06:58] So, yeah, you could do that. If that's not enough, there's so many really good promise libraries out there on node. Bluebird is a really good one. Although, I haven't used it in my years, because I haven't had the need to. Because of what async/await. But bluebird literally did they have so many promise methods on there that you can do so much control flow it's ridiculous.
[00:07:15] It's overkill, it's like a bazooka on a cockroach. It's way too much. If you want to do some crazy control full of promises, `npm install bluebird`. Check that out.