Would you like to inspect the original subtitles? These are the user uploaded subtitles that are being translated:
1
00:00:01,210 --> 00:00:04,370
In this lecture, let's implement a better way
2
00:00:04,370 --> 00:00:07,853
of catching errors in all our async functions.
3
00:00:09,310 --> 00:00:12,180
So right now, in all our async functions,
4
00:00:12,180 --> 00:00:15,750
we have these try catch blocks, right?
5
00:00:15,750 --> 00:00:20,430
So, remember how we added to all of these handle functions
6
00:00:20,430 --> 00:00:23,930
this try and then this catch block, okay?
7
00:00:23,930 --> 00:00:26,430
And so all of them have this
8
00:00:26,430 --> 00:00:28,900
because all of them are async functions
9
00:00:28,900 --> 00:00:31,930
and that's how we usually catch the errors
10
00:00:31,930 --> 00:00:33,863
inside of an asynchronous function.
11
00:00:34,800 --> 00:00:37,100
So using a try catch block.
12
00:00:37,100 --> 00:00:41,170
Now that really makes our code look messy and unfocused
13
00:00:41,170 --> 00:00:44,740
so the goal of this createTour method here, for example,
14
00:00:44,740 --> 00:00:46,560
is to just run this code.
15
00:00:46,560 --> 00:00:48,500
We actually do not want to mess around
16
00:00:48,500 --> 00:00:49,934
with error handling here,
17
00:00:49,934 --> 00:00:53,450
so right now we have these two extra blocks,
18
00:00:53,450 --> 00:00:55,690
try and catch, and with that comes
19
00:00:55,690 --> 00:00:57,900
this extra indentation here
20
00:00:57,900 --> 00:01:01,730
and so again, this really makes our code look not clean.
21
00:01:01,730 --> 00:01:03,550
It's really not focused.
22
00:01:03,550 --> 00:01:05,940
Also, we have a lot of duplicate code here
23
00:01:05,940 --> 00:01:07,830
because in each of these handlers,
24
00:01:07,830 --> 00:01:10,310
we have quite a similar catch block.
25
00:01:10,310 --> 00:01:12,250
So in all of this, all we're doing is
26
00:01:12,250 --> 00:01:14,690
really to send this response.
27
00:01:14,690 --> 00:01:17,490
And that response would actually not even be sent here
28
00:01:17,490 --> 00:01:20,900
but instead in our global error handling middleware,
29
00:01:20,900 --> 00:01:23,010
remember, but that's another topic.
30
00:01:23,010 --> 00:01:24,910
For now, what I'm trying to focus here
31
00:01:24,910 --> 00:01:27,170
is that these try catch blocks inside
32
00:01:27,170 --> 00:01:30,840
of each of our async functions are not ideal
33
00:01:30,840 --> 00:01:34,010
and so let's now try to fix that.
34
00:01:34,010 --> 00:01:37,100
And the solution is to basically take the try catch block
35
00:01:37,100 --> 00:01:39,890
out of here and put it on a higher level
36
00:01:39,890 --> 00:01:41,450
in another function.
37
00:01:41,450 --> 00:01:43,000
So basically what we're gonna do
38
00:01:43,000 --> 00:01:44,470
is to create a function,
39
00:01:44,470 --> 00:01:49,326
and then wrap this async function into that function.
40
00:01:49,326 --> 00:01:50,630
All right?
41
00:01:50,630 --> 00:01:53,333
And so let me call that one catchAsync.
42
00:01:56,960 --> 00:02:00,290
So catchAsync, and I'm calling it this way
43
00:02:00,290 --> 00:02:02,380
because the goal of this function
44
00:02:02,380 --> 00:02:05,410
is to simply catch our asynchronous errors.
45
00:02:05,410 --> 00:02:06,613
So simple, right?
46
00:02:07,500 --> 00:02:09,840
So into this catchAsync function,
47
00:02:09,840 --> 00:02:13,660
we will pass in a function, okay?
48
00:02:13,660 --> 00:02:16,820
And remember, the function that we're gonna pass in
49
00:02:16,820 --> 00:02:19,030
is basically this one.
50
00:02:19,030 --> 00:02:21,678
So now that we're working with this example
51
00:02:21,678 --> 00:02:25,420
the function that we will pass into the catchAsync
52
00:02:25,420 --> 00:02:27,840
is this function because this is where we want
53
00:02:27,840 --> 00:02:30,033
to catch the asynchronous errors.
54
00:02:31,030 --> 00:02:32,563
So let's actually do that.
55
00:02:34,090 --> 00:02:39,090
So fn, and then wrap that entire function into there.
56
00:02:40,950 --> 00:02:43,340
So next up, what we then have to do
57
00:02:43,340 --> 00:02:45,440
is to actually call this function in here.
58
00:02:46,670 --> 00:02:49,640
So call it, and this function should receive
59
00:02:49,640 --> 00:02:53,810
request, response, and in fact, also next.
60
00:02:53,810 --> 00:02:57,440
So this one here should actually also have next
61
00:02:57,440 --> 00:02:58,860
and all the others, as well,
62
00:02:58,860 --> 00:03:01,260
because remember, we need the next function
63
00:03:01,260 --> 00:03:03,540
in order to pass the error into it
64
00:03:03,540 --> 00:03:05,660
so that that error can then be handled
65
00:03:05,660 --> 00:03:08,470
in the global error handling middleware.
66
00:03:08,470 --> 00:03:10,360
So all of these functions are gonna need
67
00:03:10,360 --> 00:03:12,063
request, response, and next.
68
00:03:12,950 --> 00:03:14,540
But let's leave that for later.
69
00:03:14,540 --> 00:03:17,090
For now, let's really focus on our catchAsync here.
70
00:03:19,180 --> 00:03:22,120
So this function here that we passed into async,
71
00:03:22,120 --> 00:03:24,290
which is now called fn up here,
72
00:03:24,290 --> 00:03:26,040
is an asynchronous function.
73
00:03:26,040 --> 00:03:28,080
And remember that asynchronous functions
74
00:03:28,080 --> 00:03:30,490
return promises, right?
75
00:03:30,490 --> 00:03:33,500
And when there is an error inside of an async function,
76
00:03:33,500 --> 00:03:37,310
that basically means that the promise gets rejected.
77
00:03:37,310 --> 00:03:40,160
And so up here, where we actually call that function,
78
00:03:40,160 --> 00:03:41,893
we can then catch that error.
79
00:03:43,790 --> 00:03:46,040
So we catch it here, instead of catching it
80
00:03:46,040 --> 00:03:48,590
in the try catch block.
81
00:03:48,590 --> 00:03:53,590
So catch, and error, and then next, and pass the error.
82
00:03:57,040 --> 00:03:58,160
And we can simplify this,
83
00:03:58,160 --> 00:04:01,810
but for now let's remove the try catch block here,
84
00:04:01,810 --> 00:04:05,103
and so simply focus on this piece.
85
00:04:07,580 --> 00:04:08,920
So this is all we want
86
00:04:08,920 --> 00:04:12,110
and we no longer need the try catch block,
87
00:04:12,110 --> 00:04:15,660
again, because that catch is now basically transferred
88
00:04:15,660 --> 00:04:17,113
to here, to this line.
89
00:04:18,500 --> 00:04:20,350
It's no longer a catch block,
90
00:04:20,350 --> 00:04:22,560
because in here it's just easier to use
91
00:04:22,560 --> 00:04:26,060
the promise that the fn function returns.
92
00:04:26,060 --> 00:04:29,640
So again, this fn function is this function,
93
00:04:29,640 --> 00:04:32,270
so the one that we passed into catchAsync,
94
00:04:32,270 --> 00:04:34,650
and so that is gonna return a promise.
95
00:04:34,650 --> 00:04:37,100
And actually, I noticed here that this, of course,
96
00:04:37,100 --> 00:04:40,110
should be called catchAsync, all right?
97
00:04:40,110 --> 00:04:41,800
And then so that function that we passed
98
00:04:41,800 --> 00:04:45,447
into catchAsync, this one is of course then fn.
99
00:04:45,447 --> 00:04:46,280
All right?
100
00:04:46,280 --> 00:04:48,980
So the argument that we passed in there.
101
00:04:48,980 --> 00:04:51,590
Now there are actually two big problems
102
00:04:51,590 --> 00:04:54,180
with the way that this is implemented right now
103
00:04:54,180 --> 00:04:57,240
and so this way, it wouldn't really work at all.
104
00:04:57,240 --> 00:04:59,340
So first one, this function call here
105
00:04:59,340 --> 00:05:03,213
has no way of knowing request, response, and next.
106
00:05:04,300 --> 00:05:07,460
We did not pass them into catchAsync here,
107
00:05:07,460 --> 00:05:09,300
and so really there's no way
108
00:05:09,300 --> 00:05:12,693
for the function to know the values of these parameters.
109
00:05:13,658 --> 00:05:15,610
And second is that right here
110
00:05:15,610 --> 00:05:18,473
we are actually calling the async function.
111
00:05:20,290 --> 00:05:22,290
And to see this a bit better, let's just
112
00:05:23,200 --> 00:05:24,873
get completely rid of this code.
113
00:05:26,370 --> 00:05:29,520
So here we have catchAsync and we are then calling it
114
00:05:29,520 --> 00:05:31,153
using the parentheses of course.
115
00:05:32,350 --> 00:05:34,900
And then inside of catchAsync we are also then
116
00:05:34,900 --> 00:05:37,760
right away calling the fn function,
117
00:05:37,760 --> 00:05:40,130
and that's not how it is supposed to work.
118
00:05:40,130 --> 00:05:43,060
So createTour here should really be a function
119
00:05:43,060 --> 00:05:45,840
but not the result of calling a function.
120
00:05:45,840 --> 00:05:47,810
But that's right now what's happening.
121
00:05:47,810 --> 00:05:49,940
So right now catchAsync is being called,
122
00:05:49,940 --> 00:05:54,310
which then calls this function here, okay?
123
00:05:54,310 --> 00:05:56,890
And so again, this function should not called,
124
00:05:56,890 --> 00:05:59,360
but instead it should sit here and wait
125
00:05:59,360 --> 00:06:01,460
until express calls it.
126
00:06:01,460 --> 00:06:03,310
And express will of course call it
127
00:06:03,310 --> 00:06:05,400
as soon as someone hits the route
128
00:06:05,400 --> 00:06:08,390
that needs this control function.
129
00:06:08,390 --> 00:06:11,980
And so the solution to that is to basically make
130
00:06:11,980 --> 00:06:15,030
the catchAsync function return another function
131
00:06:15,030 --> 00:06:18,060
which is then gonna be assigned to createTour
132
00:06:18,060 --> 00:06:19,640
and so that function can then
133
00:06:19,640 --> 00:06:21,483
later be called when necessary.
134
00:06:23,294 --> 00:06:24,394
So let's do that here.
135
00:06:25,590 --> 00:06:28,480
So let's return an anonymous function
136
00:06:28,480 --> 00:06:30,890
and so remember that this is the function
137
00:06:30,890 --> 00:06:32,900
that express is then gonna call.
138
00:06:32,900 --> 00:06:35,380
And so here is where we then specify
139
00:06:35,380 --> 00:06:38,423
request, response, and next.
140
00:06:41,120 --> 00:06:43,763
Actually missing the arrow here.
141
00:06:47,230 --> 00:06:48,480
And all right.
142
00:06:48,480 --> 00:06:49,890
And that's actually it.
143
00:06:49,890 --> 00:06:52,420
That's our catchAsync function.
144
00:06:52,420 --> 00:06:54,610
Just remember how I said that we could simplify it
145
00:06:54,610 --> 00:06:56,840
and that's just because, in JavaScript,
146
00:06:56,840 --> 00:06:59,110
we can simplify it like this
147
00:06:59,110 --> 00:07:01,777
so all we need to pass here is the function,
148
00:07:01,777 --> 00:07:04,020
and it will then be called automatically
149
00:07:04,020 --> 00:07:06,810
with the parameter that this callback receives.
150
00:07:06,810 --> 00:07:09,263
So it's the same as writing next.
151
00:07:11,500 --> 00:07:13,290
So let's recap here.
152
00:07:13,290 --> 00:07:16,490
So in order to get rid our try catch blocks,
153
00:07:16,490 --> 00:07:19,230
we simply wrapped our asynchronous function
154
00:07:19,230 --> 00:07:23,010
inside of the catchAsync function that we just created.
155
00:07:23,010 --> 00:07:26,160
This function will then return a new anonymous function,
156
00:07:26,160 --> 00:07:27,690
which is this one here,
157
00:07:27,690 --> 00:07:31,660
which will then be assigned to createTour.
158
00:07:31,660 --> 00:07:34,200
And so basically it is this function here
159
00:07:34,200 --> 00:07:36,940
that will get called as soon as a new tour
160
00:07:36,940 --> 00:07:40,010
should be created using the createTour handler.
161
00:07:40,010 --> 00:07:42,960
And so that's why it has the exact same signature here
162
00:07:42,960 --> 00:07:47,520
as this async function, with request, response, and next.
163
00:07:47,520 --> 00:07:49,740
Now what this function here will then do
164
00:07:49,740 --> 00:07:51,320
is that it will call the function
165
00:07:51,320 --> 00:07:53,440
that we passed in initially,
166
00:07:53,440 --> 00:07:54,990
so this one here,
167
00:07:54,990 --> 00:07:58,270
and it will then execute all the code that is in there.
168
00:07:58,270 --> 00:08:00,670
Now since it's an async function here,
169
00:08:00,670 --> 00:08:02,380
it will return a promise
170
00:08:02,380 --> 00:08:05,610
and therefore, in case there is an error in this promise
171
00:08:05,610 --> 00:08:08,400
or in other words, in case it gets rejected,
172
00:08:08,400 --> 00:08:11,090
we can then catch the error that happened
173
00:08:11,090 --> 00:08:15,193
using the catch method that is available on all promises.
174
00:08:16,560 --> 00:08:19,510
And in the end, it is this catch method here
175
00:08:19,510 --> 00:08:22,670
which will pass the error into the next function
176
00:08:22,670 --> 00:08:24,780
which will then make it so that our error
177
00:08:24,780 --> 00:08:27,943
ends up in our global error handling middleware.
178
00:08:28,890 --> 00:08:31,020
So this here, this line of code,
179
00:08:31,020 --> 00:08:33,510
is really where all the magic happens,
180
00:08:33,510 --> 00:08:35,440
and this is, in fact, what allows us
181
00:08:35,440 --> 00:08:38,893
to get rid of the catch block that we had previously.
182
00:08:39,770 --> 00:08:40,602
And a note:
183
00:08:40,602 --> 00:08:43,710
this is quite complicated to wrap your head around
184
00:08:43,710 --> 00:08:46,460
and in case that it's not 100% clear,
185
00:08:46,460 --> 00:08:48,943
don't worry, it's not all that important.
186
00:08:49,792 --> 00:08:53,010
This is really just about figuring out how exactly
187
00:08:53,010 --> 00:08:56,460
asynchronous code works behind the scenes in JavaScript.
188
00:08:56,460 --> 00:09:00,100
So it's not really so much about express or Node.js,
189
00:09:00,100 --> 00:09:04,060
this is more about how asynchronous code works.
190
00:09:04,060 --> 00:09:06,560
Now anyway, if we now create a new tour
191
00:09:06,560 --> 00:09:08,040
and some error happens,
192
00:09:08,040 --> 00:09:10,440
for example, from an invalid input,
193
00:09:10,440 --> 00:09:13,450
then that error should of course be catched here
194
00:09:13,450 --> 00:09:15,120
in this catch function,
195
00:09:15,120 --> 00:09:18,270
and will then be propagated to our error handling middleware
196
00:09:18,270 --> 00:09:21,870
and so that one will then send back the error response
197
00:09:21,870 --> 00:09:24,570
that we're expected to receive.
198
00:09:24,570 --> 00:09:26,973
And so let's now actually try that out.
199
00:09:28,080 --> 00:09:30,500
So create a new tour.
200
00:09:30,500 --> 00:09:32,030
Here we have the body,
201
00:09:32,030 --> 00:09:35,223
and let's now get rid of one of these required fields.
202
00:09:36,440 --> 00:09:37,273
All right.
203
00:09:37,273 --> 00:09:40,223
And so that should trigger an error, and so let's see.
204
00:09:41,220 --> 00:09:44,920
And indeed, our tour validation failed,
205
00:09:44,920 --> 00:09:46,910
which is exactly the error message
206
00:09:46,910 --> 00:09:49,090
that we were supposed to receive.
207
00:09:49,090 --> 00:09:53,220
Now here, you see this 500 Internal Server Error,
208
00:09:53,220 --> 00:09:55,710
which is simply due to the fact that right now
209
00:09:55,710 --> 00:09:57,500
the error that was propagated
210
00:09:57,500 --> 00:09:59,280
to the error handling middleware
211
00:09:59,280 --> 00:10:02,110
did not have any status code specified
212
00:10:02,110 --> 00:10:05,190
and so remember our default is 500
213
00:10:05,190 --> 00:10:08,310
and so that's the one that was then sent back.
214
00:10:08,310 --> 00:10:10,060
And of course, we need to fix that
215
00:10:10,060 --> 00:10:13,173
and we will do that in a later lecture in this course.
216
00:10:14,730 --> 00:10:17,030
For now, what matters here is that first,
217
00:10:17,030 --> 00:10:20,420
our catchAsync function works just as intended,
218
00:10:20,420 --> 00:10:23,700
and second, that the error was actually propagated,
219
00:10:23,700 --> 00:10:26,900
so it was catched by our global error handling middleware
220
00:10:26,900 --> 00:10:30,223
which then sent this response back to the client.
221
00:10:32,520 --> 00:10:35,360
Now let's actually go ahead and export
222
00:10:35,360 --> 00:10:38,010
this catch function into its own file.
223
00:10:38,010 --> 00:10:39,950
So I'm grabbing it from here
224
00:10:39,950 --> 00:10:42,200
and I will create just another file
225
00:10:42,200 --> 00:10:43,843
into our utilities folder.
226
00:10:47,060 --> 00:10:51,123
So catchAsync.js.
227
00:10:55,470 --> 00:11:00,470
And to here, module.exports should be just this.
228
00:11:04,650 --> 00:11:09,450
And so that should work just fine.
229
00:11:09,450 --> 00:11:11,340
Back in our tour controller we of course
230
00:11:11,340 --> 00:11:13,373
now need to import this function.
231
00:11:18,970 --> 00:11:21,840
And as usual, we need to go up one folder
232
00:11:22,840 --> 00:11:25,690
and then into our utilities folder
233
00:11:25,690 --> 00:11:27,733
and then catchAsync.
234
00:11:30,810 --> 00:11:32,840
All right, and now all we need to do
235
00:11:32,840 --> 00:11:36,080
is to get rid of all these catch blocks
236
00:11:36,080 --> 00:11:40,593
and wrap all the handlers into the catchAsync.
237
00:11:42,210 --> 00:11:43,793
So let's do that.
238
00:11:47,610 --> 00:11:52,610
First do the wrapping, and then getting rid of these blocks.
239
00:11:57,030 --> 00:12:00,220
Give it a save to reformat, and here we go.
240
00:12:00,220 --> 00:12:03,310
And now it's simply a process of repeating this
241
00:12:03,310 --> 00:12:06,821
until all of the tours, or,
242
00:12:06,821 --> 00:12:09,633
sorry, until all of the handlers are done.
243
00:12:13,070 --> 00:12:14,760
Okay, quick save.
244
00:12:14,760 --> 00:12:16,740
This one is already done.
245
00:12:16,740 --> 00:12:18,763
Next up is update.
246
00:12:26,920 --> 00:12:28,483
And only one more missing.
247
00:12:36,380 --> 00:12:37,870
Or actually, that's not true.
248
00:12:37,870 --> 00:12:40,403
Down there we have even more async functions.
249
00:12:52,530 --> 00:12:57,203
So we'll get rid of the catch and the try here.
250
00:12:59,150 --> 00:13:01,100
And I believe this one is the last one.
251
00:13:04,020 --> 00:13:05,483
And yeah, indeed it is.
252
00:13:12,390 --> 00:13:15,000
All right, now one other thing that we need to do
253
00:13:15,000 --> 00:13:19,040
is actually add next to all of them here as well.
254
00:13:19,040 --> 00:13:20,793
But of course, not in uppercase.
255
00:13:21,690 --> 00:13:22,960
Okay.
256
00:13:22,960 --> 00:13:25,480
And let me actually just select all of them here
257
00:13:28,170 --> 00:13:30,683
so that I only have to write it once.
258
00:13:33,140 --> 00:13:35,943
And so that added it to all of them.
259
00:13:38,390 --> 00:13:42,063
And so now I guess we're done with this part.
260
00:13:43,270 --> 00:13:46,310
Let's just very quickly test it again,
261
00:13:46,310 --> 00:13:48,733
not with this one, but here with,
262
00:13:49,950 --> 00:13:52,000
not with this one as well, so we're done.
263
00:13:55,330 --> 00:13:57,140
And I'm gonna try to get a tour
264
00:13:57,140 --> 00:14:01,870
but with an invalid ID, so let's see what happens here.
265
00:14:01,870 --> 00:14:04,250
And indeed, we get our error message
266
00:14:04,250 --> 00:14:06,950
and again with the 500 status code,
267
00:14:06,950 --> 00:14:08,640
which is not correct, remember,
268
00:14:08,640 --> 00:14:10,050
but we're gonna take care of that
269
00:14:10,050 --> 00:14:11,930
at a later point in time.
270
00:14:11,930 --> 00:14:15,130
So right now, let me show you
271
00:14:15,130 --> 00:14:19,920
that this here is where the 500 comes from
272
00:14:19,920 --> 00:14:22,200
because right now there's no status code
273
00:14:22,200 --> 00:14:24,310
inside of the error that we get
274
00:14:24,310 --> 00:14:27,940
because these errors, they actually come from Mongoose
275
00:14:27,940 --> 00:14:29,730
and so we have no way of adding
276
00:14:29,730 --> 00:14:32,390
a status code to these errors.
277
00:14:32,390 --> 00:14:35,370
Or actually, of course, we could do it,
278
00:14:35,370 --> 00:14:37,950
but that would just be even more confusing
279
00:14:37,950 --> 00:14:40,330
and so we're gonna find another way
280
00:14:40,330 --> 00:14:41,443
later in this section.
281
00:14:42,510 --> 00:14:45,840
For now, I'm really happy with the result that we have here
282
00:14:45,840 --> 00:14:48,773
and so that's it for this lecture.
21961
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.