1 00:00:00,150 --> 00:00:03,630 As mentioned in the last video there's one more topic I want to cover. 2 00:00:03,630 --> 00:00:10,020 Related to asynchronous programming before we get back to adding new API roots to the task manager app 3 00:00:10,290 --> 00:00:12,250 and that is async await. 4 00:00:12,390 --> 00:00:17,970 Now I've been working with JavaScript for over a decade and I remember when all of the features I now 5 00:00:17,970 --> 00:00:18,840 take for granted. 6 00:00:18,840 --> 00:00:26,070 First came out things like promises aero functions and others were super exciting and definitely changed 7 00:00:26,100 --> 00:00:27,270 how I wrote code. 8 00:00:27,270 --> 00:00:32,970 In my opinion out of all of those new features we've gotten in JavaScript over the years none is a bigger 9 00:00:32,970 --> 00:00:40,080 improvement to the language than async await async await makes it so easy to work with our asynchronous 10 00:00:40,140 --> 00:00:46,170 promise based code writing code that looks more synchronous than asynchronous. 11 00:00:46,170 --> 00:00:50,010 Now the good news is that async await is not a whole new thing. 12 00:00:50,310 --> 00:00:57,540 It's not like we're going from callbacks to promises to async await async await is merely a small set 13 00:00:57,540 --> 00:01:01,470 of tools that makes it easy to work with promises. 14 00:01:01,650 --> 00:01:05,910 So we're still going to be using the same old promise methods we've used before. 15 00:01:05,910 --> 00:01:07,800 Nothing's gonna change there. 16 00:01:07,830 --> 00:01:13,500 The only thing that's going to change is how we manage our code when we have a lot of asynchronous things 17 00:01:13,560 --> 00:01:14,330 going on. 18 00:01:14,400 --> 00:01:19,110 A single wait is going to play a major role in the task manager application. 19 00:01:19,110 --> 00:01:22,150 We'll be using it in every single root handler. 20 00:01:22,410 --> 00:01:27,960 So I want to take time and make sure we understand what's going on before we focus on integrating it 21 00:01:27,960 --> 00:01:29,310 into existing code. 22 00:01:29,610 --> 00:01:36,180 So to start once again with a new syntax we're going to create a new file in that playground directory 23 00:01:36,390 --> 00:01:38,290 in the node course folder. 24 00:01:38,340 --> 00:01:44,580 I'm reserving this other playground folder in the task manager directory for playground type files that 25 00:01:44,580 --> 00:01:50,520 require a database connection like this one here but to kick things off we're gonna start without worrying 26 00:01:50,520 --> 00:01:52,580 about connecting to a database. 27 00:01:52,590 --> 00:01:56,260 We'll start with simple dummy asynchronous tasks. 28 00:01:56,490 --> 00:02:02,460 Let's go ahead and get started by closing all open editors and we're going to switch over to that playground 29 00:02:02,460 --> 00:02:08,730 directory and we're going to add one more file to the list that's going to be number nine which I can 30 00:02:08,730 --> 00:02:15,450 call a sink python a weight which is the name of the feature we'll be exploring and then down below 31 00:02:15,450 --> 00:02:16,710 in the terminal. 32 00:02:16,710 --> 00:02:22,290 I'm gonna shut things down and navigate over to that directory as well like we've done plenty of times 33 00:02:22,320 --> 00:02:23,450 before. 34 00:02:23,520 --> 00:02:28,740 Now let's go ahead and get started with async a wait and see what it can do for us to get started. 35 00:02:28,770 --> 00:02:31,670 We're going to create the simplest function possible. 36 00:02:31,710 --> 00:02:37,200 I'm going to create a constant do work and we're going to set up the value as an arrow function. 37 00:02:37,230 --> 00:02:43,080 Now for this arrow function for the moment we're not going to accept any parameters and we're not even 38 00:02:43,080 --> 00:02:44,130 going to do anything. 39 00:02:44,130 --> 00:02:47,580 We're gonna have an empty function body down below. 40 00:02:47,640 --> 00:02:53,220 We're gonna go ahead and call this function printing its return value to the terminal. 41 00:02:53,220 --> 00:02:57,240 Right here we'll use console dot log to print something. 42 00:02:57,240 --> 00:02:58,410 What do I want to print. 43 00:02:58,410 --> 00:03:01,740 I want to print whatever comes back from calling do work. 44 00:03:01,800 --> 00:03:05,830 So I'm taking that return value and passing it to console log. 45 00:03:06,210 --> 00:03:09,290 Now what do we know about JavaScript functions. 46 00:03:09,300 --> 00:03:16,490 We know that if we don't explicitly return something from the function undefined is implicitly returned. 47 00:03:16,530 --> 00:03:21,200 So if I was to run the program I would expect to see undefined printing. 48 00:03:21,270 --> 00:03:23,160 Let's go ahead and do just that. 49 00:03:23,250 --> 00:03:25,710 I'm gonna save the script down below. 50 00:03:25,710 --> 00:03:31,450 I'm going to run it node 9 async await dot J S. 51 00:03:31,620 --> 00:03:35,200 Now when I do so we're gonna get exactly what we expected. 52 00:03:35,430 --> 00:03:37,830 I have undefined printing. 53 00:03:37,920 --> 00:03:44,490 Now the reason I'm doing this is because what we're about to do is use async await the first part of 54 00:03:44,490 --> 00:03:46,500 the feature is a sync. 55 00:03:46,530 --> 00:03:49,430 This allows us to create an async function. 56 00:03:49,590 --> 00:03:52,890 And in that function we can use the await feature. 57 00:03:52,890 --> 00:03:57,940 Now this will all make sense once we have a more complete example to start. 58 00:03:57,960 --> 00:04:03,050 Essentially what we need to do is mark a function as an async function. 59 00:04:03,240 --> 00:04:08,980 And this is done by adding the async keyword right before the function declaration. 60 00:04:09,000 --> 00:04:12,880 So right here I have the same old function I had just moments ago. 61 00:04:12,990 --> 00:04:17,020 The only thing I've done is I've added a sink right up front. 62 00:04:17,080 --> 00:04:22,590 Now with this simple change we're actually also changing the behavior of our program. 63 00:04:22,590 --> 00:04:26,410 We're no longer going to get undefined printing in the terminal. 64 00:04:26,460 --> 00:04:29,100 Let's go ahead and rerun the script and see what we get. 65 00:04:29,100 --> 00:04:31,460 I'm going to rerun the script and what do I get. 66 00:04:31,470 --> 00:04:35,570 I no longer get undefined like I was getting before. 67 00:04:35,610 --> 00:04:42,780 Instead what I can see is that do work is returning a promise and that promise has been fulfilled with 68 00:04:42,780 --> 00:04:44,430 the value undefined. 69 00:04:44,790 --> 00:04:53,340 So this is the first important thing to note about async functions async functions always return a promise 70 00:04:53,550 --> 00:05:01,070 that promise is fulfilled with the value you the developer choose to return from the function let's 71 00:05:01,070 --> 00:05:02,700 go ahead and clarify that. 72 00:05:02,810 --> 00:05:08,390 Right now we're seeing the promise get fulfilled with undefined because that's what we're returning 73 00:05:08,540 --> 00:05:13,840 by not explicitly returning anything undefined is implicitly returned. 74 00:05:13,850 --> 00:05:16,660 Let's go ahead and explicitly return something. 75 00:05:16,730 --> 00:05:20,900 I'm going to return a string with my name Andrew. 76 00:05:20,900 --> 00:05:25,190 Now we're going to save this script and we're going to rerun things once again. 77 00:05:25,190 --> 00:05:32,530 Now we have changed the return value but I mentioned that async functions always return a promise. 78 00:05:32,570 --> 00:05:36,280 So the return value of do work is not a string. 79 00:05:36,290 --> 00:05:38,520 It's not this string right here. 80 00:05:38,570 --> 00:05:43,160 Instead it's a promise that gets fulfilled with this string. 81 00:05:43,640 --> 00:05:46,640 So down below we rerun the script from the terminal. 82 00:05:46,640 --> 00:05:48,510 And that's exactly what I see. 83 00:05:48,640 --> 00:05:54,180 If you return value from do work is a promise that has been fulfilled with the string. 84 00:05:54,320 --> 00:05:55,040 Andrew. 85 00:05:55,040 --> 00:06:00,980 Now since we are getting a promise back from due work we can actually use then and catch our promised 86 00:06:00,980 --> 00:06:05,420 methods instead of just taking the promise and dumping it to the console. 87 00:06:05,450 --> 00:06:11,900 So I'm going to remove this console dot log statement and replace it with a call to do work exactly 88 00:06:11,900 --> 00:06:13,080 like we had before. 89 00:06:13,500 --> 00:06:18,260 Then I'll set up a then call to run some code when the promise is fulfilled. 90 00:06:18,350 --> 00:06:21,420 And right here I'll get access to the results. 91 00:06:21,500 --> 00:06:26,270 Now in this case the result is whatever value is returned from do work. 92 00:06:26,480 --> 00:06:31,780 So right here console dot log printing inside of quotes. 93 00:06:31,790 --> 00:06:35,780 The string result followed by the result variable. 94 00:06:35,780 --> 00:06:39,650 So I'm printing it twice once as a label for what I'm seeing. 95 00:06:39,650 --> 00:06:42,100 And then once as the actual value. 96 00:06:42,290 --> 00:06:44,480 And we can also set up a catch call. 97 00:06:44,510 --> 00:06:50,370 So down below a call to catch we're going to set up a function that gets an error. 98 00:06:50,510 --> 00:06:52,530 And right here we'll do the same thing. 99 00:06:52,550 --> 00:06:56,110 Let's go ahead and use the correct syntax for the Arrow function though. 100 00:06:56,120 --> 00:06:56,980 Perfect. 101 00:06:56,990 --> 00:07:00,020 And now we'll use console dot log. 102 00:07:00,020 --> 00:07:04,270 I'll print these string e followed by the actual error. 103 00:07:04,280 --> 00:07:11,000 Now if we run this program since the promise does indeed fulfill with this value I would expect to see 104 00:07:11,060 --> 00:07:17,210 this code run and I would expect to get my result I'm going to save this script rerun things from the 105 00:07:17,210 --> 00:07:18,740 terminal down below. 106 00:07:18,740 --> 00:07:20,910 And that's exactly what we get. 107 00:07:20,930 --> 00:07:23,330 Now how do we ever get catch to run. 108 00:07:23,330 --> 00:07:30,260 Well if we throw an error from our async function that's going to be the same as rejecting the promise 109 00:07:30,320 --> 00:07:33,020 that comes back from the async function. 110 00:07:33,020 --> 00:07:39,170 So when I return a value we're fulfilling that promise with the value we just saw that right here when 111 00:07:39,170 --> 00:07:42,770 I throw an error we're rejecting the promise with that error. 112 00:07:43,340 --> 00:07:49,340 So throw new error and we can pick whatever message we like. 113 00:07:49,340 --> 00:07:53,320 Something went wrong. 114 00:07:53,330 --> 00:07:54,410 Perfect. 115 00:07:54,440 --> 00:08:00,080 Now that we have our throw statement in place let's go ahead and actually run the program one more time 116 00:08:00,560 --> 00:08:02,200 from the terminal down below. 117 00:08:02,240 --> 00:08:08,390 I would expect that my catch function runs and that is exactly what happens if I scroll up I can see 118 00:08:08,390 --> 00:08:11,870 I got my little E string which comes from right here. 119 00:08:11,870 --> 00:08:15,980 Then I have the entire error object printing out down below. 120 00:08:15,980 --> 00:08:17,090 So there we go. 121 00:08:17,120 --> 00:08:20,780 This is the basic structure of an asynchronous function. 122 00:08:20,810 --> 00:08:23,800 The question is why is this useful. 123 00:08:23,810 --> 00:08:30,290 What's the other half to the feature that actually allows us to manage our asynchronous tasks with ease. 124 00:08:30,290 --> 00:08:35,280 This brings us to the other half of async await which is the await operator. 125 00:08:35,330 --> 00:08:39,200 Now the await operator can only be used in async functions. 126 00:08:39,200 --> 00:08:43,640 And now that we have an async function in place we're ready to talk about a wait. 127 00:08:43,640 --> 00:08:49,550 Remember the whole point of async await is to make it easier to work with asynchronous promise based 128 00:08:49,550 --> 00:08:50,400 code. 129 00:08:50,420 --> 00:08:54,170 So let's bring one of our dummy promise functions into the mix. 130 00:08:54,170 --> 00:08:56,480 We don't have to recreate it from scratch. 131 00:08:56,510 --> 00:09:00,710 Let's go ahead and just copy it from our previous playground script. 132 00:09:00,740 --> 00:09:05,810 Right here we have a function that adds up to numbers after two seconds. 133 00:09:05,900 --> 00:09:12,140 I'm gonna take that function in its entirety and I'm going to copy it over to our async await playground 134 00:09:12,140 --> 00:09:15,270 file without changing a single thing about it. 135 00:09:15,560 --> 00:09:19,190 And this is done intentionally when working with async await. 136 00:09:19,280 --> 00:09:22,910 You don't have to change how your promises function internally. 137 00:09:23,000 --> 00:09:25,890 All you do is change how you work with them. 138 00:09:25,970 --> 00:09:32,690 For us that means that Mongoose doesn't need to rewrite the library in order for us to use async await 139 00:09:33,020 --> 00:09:35,160 Mongoose supports promises. 140 00:09:35,210 --> 00:09:41,720 So as a consumer of those promises we can use async await if we wanted to down below. 141 00:09:41,720 --> 00:09:44,600 Let's see how a weight is actually going to help us. 142 00:09:44,600 --> 00:09:49,750 So inside of due work we're going to work with ad calling it a few different times. 143 00:09:49,760 --> 00:09:51,850 Now if we weren't using async await. 144 00:09:51,890 --> 00:09:57,140 I know exactly how I could call add a couple of times adding up some numbers because we did that a few 145 00:09:57,140 --> 00:10:01,580 videos ago in that promise this file we have that down below. 146 00:10:01,580 --> 00:10:09,050 I call ad adding on my first then method I provide the callback where I return the another promise right 147 00:10:09,050 --> 00:10:09,350 here. 148 00:10:09,350 --> 00:10:13,110 Adding up more numbers and I get that result down below. 149 00:10:13,130 --> 00:10:18,140 That's not what it's going to look like with async await we're going to remove the need for all of those 150 00:10:18,140 --> 00:10:19,760 callback functions. 151 00:10:20,060 --> 00:10:28,070 So what we get access to in a sync is the await operator V a wait operator gets used with a promise 152 00:10:28,190 --> 00:10:31,720 we can get a promise because ad returns a promise. 153 00:10:31,730 --> 00:10:38,120 So right here I'm going to call ad to use a wait with a promise and I'll go ahead and add up a couple 154 00:10:38,120 --> 00:10:38,930 of numbers. 155 00:10:39,080 --> 00:10:42,510 I'm gonna add up the number one with the number ninety nine. 156 00:10:42,560 --> 00:10:48,010 Now the sum is one hundred but the question is where do I get access to that data. 157 00:10:48,080 --> 00:10:54,410 If I wasn't using a sink and a weight I would add on a then method call provide my callback function 158 00:10:54,500 --> 00:10:59,130 and I'd get access to the data inside of there with async and a. 159 00:10:59,210 --> 00:11:06,440 It looks as if ad is a standard synchronous function we actually can create a variable right here to 160 00:11:06,440 --> 00:11:11,450 get access to the value that the promise is fulfilled with. 161 00:11:11,450 --> 00:11:15,230 So in this case yes we still have to wait those two seconds. 162 00:11:15,230 --> 00:11:18,380 The advantage is syntactical right here. 163 00:11:18,380 --> 00:11:25,370 It's a lot easier to reason about and pass this code than it is the code we have in the other file. 164 00:11:25,400 --> 00:11:30,290 Now from here I can go ahead and return that sum which is exactly what I'm going to do. 165 00:11:30,380 --> 00:11:33,490 Then we'll go ahead and run the program down below. 166 00:11:33,560 --> 00:11:39,080 I'm going to clear the terminal output just to clean things up a little bit and I'll rerun the script 167 00:11:39,080 --> 00:11:46,700 by using the up arrow twice and enter and when I do so I wait my two seconds I get my result one hundred 168 00:11:46,700 --> 00:11:53,000 back so we can see right here that we're able to use code that looks synchronous to perform asynchronous 169 00:11:53,000 --> 00:11:54,010 tasks. 170 00:11:54,020 --> 00:12:00,130 Now we're only doing a single asynchronous thing right here so it might be hard to see the advantage. 171 00:12:00,170 --> 00:12:02,970 Let's go ahead and switch this function up a little bit. 172 00:12:02,990 --> 00:12:08,270 I'm going to remove the return to some and we're going to add up more numbers so I'm going to create 173 00:12:08,270 --> 00:12:11,080 const some 2 right here. 174 00:12:11,120 --> 00:12:17,740 I'll get the value from using a wait with a another call to add I'll add up that first sum one hundred 175 00:12:17,750 --> 00:12:25,520 with the number 50 and this would be 150 then I could create some 3 going through that process once 176 00:12:25,520 --> 00:12:33,400 again adding up some 2 which is 150 with the number three which would bring me to a total of 150 3. 177 00:12:33,950 --> 00:12:39,500 So now I have some 3 and I could go ahead and return that returning some 3. 178 00:12:39,530 --> 00:12:45,110 Now in this case we are doing 3 asynchronous things and they all take 2 seconds. 179 00:12:45,110 --> 00:12:50,700 So when I rerun the program we still have to wait those six seconds using async and await. 180 00:12:50,720 --> 00:12:55,160 Does it make things fast it just makes things easier to work with. 181 00:12:55,180 --> 00:12:58,480 Right here I get one fifty three printing. 182 00:12:58,480 --> 00:13:01,030 So we wait two seconds to get one hundred. 183 00:13:01,170 --> 00:13:07,870 Then we wait on the next line to get the 150 value and then finally we wait for one fifty three. 184 00:13:07,900 --> 00:13:10,600 So here all of our code runs in order. 185 00:13:10,660 --> 00:13:17,500 Even though asynchronous things are indeed happening behind the scenes now in this case we have code 186 00:13:17,560 --> 00:13:21,630 right here that is much simpler than the promised chaining code. 187 00:13:21,640 --> 00:13:23,920 We had over here promise chaining. 188 00:13:23,950 --> 00:13:29,940 Well useful can cause problems and it's a bit easy to misunderstand what's going on. 189 00:13:29,950 --> 00:13:32,920 We have a lot of different functions and return values. 190 00:13:32,920 --> 00:13:37,200 And when we return something that impacts what happens further down the chain. 191 00:13:37,270 --> 00:13:43,990 This can get us into some confusing situations async await was added to help fight that off. 192 00:13:43,990 --> 00:13:44,550 Right here. 193 00:13:44,590 --> 00:13:46,840 It's pretty easy to see what's going on. 194 00:13:46,870 --> 00:13:50,350 Once you understand what a sink and a weight actually do. 195 00:13:50,380 --> 00:13:55,990 Another big problem with promise chaining is that it's difficult to have all of the values in the same 196 00:13:55,990 --> 00:13:56,770 scope. 197 00:13:56,800 --> 00:13:58,290 So what do I mean by that. 198 00:13:58,300 --> 00:14:04,060 Well right here we have our first some then down below in this function we have access to the second 199 00:14:04,090 --> 00:14:04,870 some. 200 00:14:04,900 --> 00:14:10,540 What if I wanted to have access to both of those sums at the same time to do something like save them 201 00:14:10,540 --> 00:14:12,980 to a database or send them to the user. 202 00:14:13,000 --> 00:14:19,150 There's no easy way to do that but we would have to do is create variables in the parent scope and then 203 00:14:19,150 --> 00:14:20,750 reassign them in here. 204 00:14:20,770 --> 00:14:24,630 And it turns into a mess really quickly with async await. 205 00:14:24,640 --> 00:14:26,950 There's no need to worry about any of that. 206 00:14:26,950 --> 00:14:33,520 I have access to all of the individual results in the exact same scope my async function allowing for 207 00:14:33,520 --> 00:14:35,080 a lot of flexibility. 208 00:14:35,080 --> 00:14:41,620 The last thing we need to discuss before we can actually use async await in the real world is what happens 209 00:14:41,650 --> 00:14:46,440 if one of these promises rejects instead of officials. 210 00:14:46,510 --> 00:14:49,860 Now our ad call up above always calls resolve. 211 00:14:49,930 --> 00:14:52,360 Let's go ahead and switch it up to call reject. 212 00:14:52,360 --> 00:14:59,050 Sometimes we're gonna say that we can only add up positive numbers if either of your numbers are negative 213 00:14:59,080 --> 00:15:00,960 we'll call reject instead. 214 00:15:00,970 --> 00:15:09,100 So right here if we're gonna see if a is less than zero then we'll use the logical or operator to see 215 00:15:09,100 --> 00:15:11,350 if B is less than zero. 216 00:15:11,350 --> 00:15:16,320 So if either of them is less than zero whether it's just one or whether it's both. 217 00:15:16,360 --> 00:15:21,370 This code is going to run I'm going to use return to stop the function execution. 218 00:15:21,370 --> 00:15:27,070 So resolve doesn't get called and I'm going to use reject to provide the error. 219 00:15:27,070 --> 00:15:32,590 I'll say something like numbers must be non negative. 220 00:15:32,590 --> 00:15:33,550 Perfect. 221 00:15:33,550 --> 00:15:36,140 So now we have a call to reject in place. 222 00:15:36,160 --> 00:15:41,410 Now the program in its current state is going to work exactly as it did before and to prove that I'll 223 00:15:41,410 --> 00:15:42,230 rerun it. 224 00:15:42,310 --> 00:15:48,940 We wait our 6 seconds all of the numbers are positive so we get our result printing from this line right 225 00:15:48,940 --> 00:15:49,740 here. 226 00:15:49,780 --> 00:15:52,410 Now let's go ahead and make one of these numbers negative. 227 00:15:52,780 --> 00:15:59,230 What I'm gonna do is make our last call to add provide minus three instead of plus three. 228 00:15:59,230 --> 00:16:00,700 Now what's gonna happen. 229 00:16:00,700 --> 00:16:07,000 Well things aren't gonna crash right away because remember when using async await things happen one 230 00:16:07,000 --> 00:16:10,930 at a time so we wait our two seconds here and everything's fine. 231 00:16:11,020 --> 00:16:16,540 Then we wait our two seconds here and everything's good and then we wait our two seconds here and we 232 00:16:16,540 --> 00:16:17,830 get that error. 233 00:16:17,830 --> 00:16:21,690 So after six seconds we're going to see that a problem occurred. 234 00:16:21,730 --> 00:16:26,360 I'll rerun the program down below to prove that's exactly what happens. 235 00:16:26,380 --> 00:16:31,750 So we're waiting the same amount of time we were waiting before because the error occurs at the very 236 00:16:31,750 --> 00:16:32,350 end. 237 00:16:32,470 --> 00:16:35,350 And then I get my error message printing. 238 00:16:35,350 --> 00:16:41,800 Now if that happened earlier on like in our first call to add we would see the error sooner if this 239 00:16:41,800 --> 00:16:48,160 promise rejects then none of the code down below is going to run it's going to skip right to the catch. 240 00:16:48,160 --> 00:16:49,600 Call down here. 241 00:16:49,600 --> 00:16:54,090 That's why we're seeing EA show up from line twenty three in our program. 242 00:16:54,130 --> 00:16:57,920 So right here with minus ninety nine in the first ad call. 243 00:16:58,030 --> 00:16:59,770 I'll go ahead and rerun things. 244 00:16:59,830 --> 00:17:00,850 Now we still have to wait. 245 00:17:00,850 --> 00:17:04,930 Those initial two seconds then we get the error message in place. 246 00:17:04,930 --> 00:17:11,320 There's no need to even run the other code because something went wrong before that code had a chance 247 00:17:11,320 --> 00:17:11,740 to run. 248 00:17:11,920 --> 00:17:13,930 That's where we're going to stop for this one. 249 00:17:13,960 --> 00:17:19,510 Now I know we spent a lot of time exploring the basic syntax but async await is going to play such a 250 00:17:19,510 --> 00:17:23,260 critical role in our task manager application. 251 00:17:23,260 --> 00:17:28,750 So I want to make sure it got the time it deserved in the next video we'll start to integrate this with 252 00:17:28,810 --> 00:17:31,010 our Mongoose method calls. 253 00:17:31,030 --> 00:17:32,550 I'm excited to get to that. 254 00:17:32,560 --> 00:17:37,630 So let's go ahead and jump right in and once again there will be a challenge where you're going to have 255 00:17:37,630 --> 00:17:39,700 to use async await on your own.