Would you like to inspect the original subtitles? These are the user uploaded subtitles that are being translated:
1
1
00:00:01,300 --> 00:00:02,620
So until now,
2
2
00:00:02,620 --> 00:00:05,399
we have always assumed that everything went well
3
3
00:00:05,399 --> 00:00:10,399
with our AJAX calls, so we never handled any errors.
4
4
00:00:10,590 --> 00:00:14,000
However, an important part of web development
5
5
00:00:14,000 --> 00:00:15,689
is to actually handle the errors
6
6
00:00:15,689 --> 00:00:19,080
because it's very common that errors happen
7
7
00:00:19,080 --> 00:00:21,020
in web applications.
8
8
00:00:21,020 --> 00:00:22,600
And so in this lecture,
9
9
00:00:22,600 --> 00:00:24,930
let's talk about how to handle errors
10
10
00:00:24,930 --> 00:00:26,073
in promises.
11
11
00:00:28,120 --> 00:00:30,950
And to start, remember that a promise
12
12
00:00:30,950 --> 00:00:35,000
in which an error happens is a rejected promise.
13
13
00:00:35,000 --> 00:00:36,210
And so in this video,
14
14
00:00:36,210 --> 00:00:39,910
we're gonna learn how to handle promise rejections.
15
15
00:00:39,910 --> 00:00:41,920
Now, actually the only way
16
16
00:00:41,920 --> 00:00:44,049
in which the fetch promise rejects
17
17
00:00:44,049 --> 00:00:48,000
is when the user loses his internet connection.
18
18
00:00:48,000 --> 00:00:50,903
And so for now, that's gonna be the only error
19
19
00:00:50,903 --> 00:00:53,160
that we will handle here.
20
20
00:00:53,160 --> 00:00:56,910
Now to simulate losing the internet connection
21
21
00:00:56,910 --> 00:00:59,010
we can go here to Network
22
22
00:00:59,010 --> 00:01:03,880
and then we can basically change the speed here to Offline.
23
23
00:01:03,880 --> 00:01:06,675
However, when we then reload the page
24
24
00:01:06,675 --> 00:01:09,202
then basically everything will disappear,
25
25
00:01:09,202 --> 00:01:12,970
and so that's not really what we want.
26
26
00:01:12,970 --> 00:01:17,680
We want to simulate that the page was first still loaded
27
27
00:01:17,680 --> 00:01:22,080
but then as the user does the request without internet
28
28
00:01:22,080 --> 00:01:25,850
then we want to see the error happening.
29
29
00:01:25,850 --> 00:01:28,780
And so let's set it back to Online
30
30
00:01:28,780 --> 00:01:30,950
and so now what we want to do
31
31
00:01:30,950 --> 00:01:33,840
is to basically only call this function here
32
32
00:01:33,840 --> 00:01:36,610
whenever the user clicks on a button.
33
33
00:01:36,610 --> 00:01:38,977
And so that will then make it easier for us
34
34
00:01:38,977 --> 00:01:42,683
to simulate losing the internet connection.
35
35
00:01:43,890 --> 00:01:47,197
So here in the HTML we already have a button,
36
36
00:01:47,197 --> 00:01:50,240
so let's comment this one out
37
37
00:01:51,570 --> 00:01:55,413
and then in the script I believe, here,
38
38
00:01:55,413 --> 00:01:59,963
so we already have it here selected as this btn.
39
39
00:02:02,846 --> 00:02:06,330
And so all we will do now is btn.addEventListener
40
40
00:02:08,590 --> 00:02:11,970
click, and then here function
41
41
00:02:15,220 --> 00:02:16,423
and just like this.
42
42
00:02:18,460 --> 00:02:21,690
Now wait, so just to see what happens here
43
43
00:02:22,800 --> 00:02:25,830
so indeed that works just fine
44
44
00:02:25,830 --> 00:02:29,593
but now watch what happens when we set ourselves Offline.
45
45
00:02:30,780 --> 00:02:34,283
Let's go back to the console and now when we do the request,
46
46
00:02:35,560 --> 00:02:38,290
then we get these errors here.
47
47
00:02:38,290 --> 00:02:41,599
So first this one here, but the one that's most important
48
48
00:02:41,599 --> 00:02:45,820
is that we now have an Uncaught promise,
49
49
00:02:45,820 --> 00:02:49,220
and so because we have failed to fetch.
50
50
00:02:49,220 --> 00:02:51,760
And so at this point for the first time
51
51
00:02:51,760 --> 00:02:54,740
the promise that's returned from the fetch function
52
52
00:02:54,740 --> 00:02:57,030
was actually rejected.
53
53
00:02:57,030 --> 00:03:00,190
And so let's no handle that rejection.
54
54
00:03:00,190 --> 00:03:03,330
Now there are two ways of handling rejections
55
55
00:03:03,330 --> 00:03:06,671
and the first one is to pass a second callback function
56
56
00:03:06,671 --> 00:03:08,483
into the then method.
57
57
00:03:10,120 --> 00:03:11,980
So the first callback function here
58
58
00:03:11,980 --> 00:03:15,450
is always gonna be called for the fulfilled promise.
59
59
00:03:15,450 --> 00:03:17,630
so for a successful one.
60
60
00:03:17,630 --> 00:03:20,290
But we can also pass in a second callback
61
61
00:03:20,290 --> 00:03:24,310
which will be called when the promise was rejected.
62
62
00:03:24,310 --> 00:03:25,453
So let's do that.
63
63
00:03:26,597 --> 00:03:29,530
And this callback function will be called with an argument
64
64
00:03:29,530 --> 00:03:32,053
which is basically the error itself.
65
65
00:03:33,700 --> 00:03:36,803
And so let's simply alert the error.
66
66
00:03:38,680 --> 00:03:41,433
Alright, so let's try that.
67
67
00:03:42,345 --> 00:03:46,200
And now we are back to having No Internet
68
68
00:03:46,200 --> 00:03:50,110
so we first need to do everything normally,
69
69
00:03:50,110 --> 00:03:51,960
so load the page.
70
70
00:03:51,960 --> 00:03:56,790
Now we lose the connection and now we do the request.
71
71
00:03:56,790 --> 00:03:59,463
And so now actually we handled the error
72
72
00:03:59,463 --> 00:04:02,800
by displaying this alert window.
73
73
00:04:02,800 --> 00:04:07,290
And the error that we saw previously down here is now gone.
74
74
00:04:07,290 --> 00:04:09,230
So now, in fact, we no longer
75
75
00:04:09,230 --> 00:04:11,920
have this Uncaught error down here
76
76
00:04:11,920 --> 00:04:15,453
because we did actually catch the error right here.
77
77
00:04:16,490 --> 00:04:20,290
So handling the error is also called catching to error,
78
78
00:04:20,290 --> 00:04:22,990
and so again, that's the reason why
79
79
00:04:22,990 --> 00:04:26,030
this error that we had here before disappeared.
80
80
00:04:26,030 --> 00:04:28,501
So it said Uncaught error, but again
81
81
00:04:28,501 --> 00:04:31,890
now we are actually catching it here.
82
82
00:04:31,890 --> 00:04:34,890
And so with this we are now handling the error
83
83
00:04:34,890 --> 00:04:39,840
that might occur in this promise here, okay.
84
84
00:04:39,840 --> 00:04:42,661
Now, in this case there are then no more errors
85
85
00:04:42,661 --> 00:04:45,900
because basically the chain stops here
86
86
00:04:45,900 --> 00:04:49,600
when this error happens and when it's handled right here.
87
87
00:04:49,600 --> 00:04:52,485
But now what if there was actually no error
88
88
00:04:52,485 --> 00:04:55,333
in this fetch promise here?
89
89
00:04:56,240 --> 00:04:58,570
So basically what if this fetch promise
90
90
00:04:58,570 --> 00:05:02,010
was actually fulfilled but then the second one here
91
91
00:05:02,010 --> 00:05:03,123
was rejected.
92
92
00:05:04,160 --> 00:05:08,400
Well then we would also have to catch an error here.
93
93
00:05:08,400 --> 00:05:10,200
So we would have to come here
94
94
00:05:11,520 --> 00:05:14,030
get this function and paste it here
95
95
00:05:14,030 --> 00:05:17,370
and also handle the error right here.
96
96
00:05:17,370 --> 00:05:20,130
However, that is a little bit annoying
97
97
00:05:20,130 --> 00:05:22,820
and so in fact there is a better way
98
98
00:05:22,820 --> 00:05:25,498
of basically handling all these errors globally
99
99
00:05:25,498 --> 00:05:28,220
just in one central place.
100
100
00:05:28,220 --> 00:05:32,370
So instead of all of these callback functions here
101
101
00:05:32,370 --> 00:05:34,203
let's just delete them.
102
102
00:05:36,160 --> 00:05:39,160
okay. So this is a lot nicer
103
103
00:05:39,160 --> 00:05:41,960
just having one callback in the then
104
104
00:05:41,960 --> 00:05:44,890
and then instead we can handle all the errors
105
105
00:05:44,890 --> 00:05:46,986
no matter where they appear in the chain
106
106
00:05:46,986 --> 00:05:51,986
right at the end of the chain by adding a catch method.
107
107
00:05:53,220 --> 00:05:54,870
And then here we can actually use
108
108
00:05:54,870 --> 00:05:56,430
the same call back function
109
109
00:05:57,560 --> 00:05:59,380
because the callback function here
110
110
00:05:59,380 --> 00:06:02,823
will also be called with the error object that occurred
111
111
00:06:02,823 --> 00:06:06,200
and so then we can handle it in some way.
112
112
00:06:06,200 --> 00:06:09,690
All right, so again this catch method here
113
113
00:06:09,690 --> 00:06:12,934
at the end of the chain will basically catch any errors
114
114
00:06:12,934 --> 00:06:16,860
that occur in any place in this whole promise chain
115
115
00:06:16,860 --> 00:06:19,160
and no matter where that is.
116
116
00:06:19,160 --> 00:06:22,230
So errors basically propagate down the chain
117
117
00:06:22,230 --> 00:06:24,100
until they are caught,
118
118
00:06:24,100 --> 00:06:26,460
and only if they're not caught anywhere
119
119
00:06:26,460 --> 00:06:28,840
then we get that Uncaught error
120
120
00:06:28,840 --> 00:06:30,590
that we saw right in the beginning.
121
121
00:06:32,090 --> 00:06:34,630
All right, so let's now try this again
122
122
00:06:34,630 --> 00:06:39,630
and we will have to put back the internet, reload the page,
123
123
00:06:40,070 --> 00:06:41,233
get back Offline.
124
124
00:06:42,750 --> 00:06:45,923
And indeed we get the same error now here,
125
125
00:06:45,923 --> 00:06:49,543
so the same alert window that we had before.
126
126
00:06:53,123 --> 00:06:57,042
Now instead of having that annoying alert window
127
127
00:06:57,042 --> 00:07:00,020
let's just lock the error to the console
128
128
00:07:00,020 --> 00:07:02,523
and create some string here.
129
129
00:07:03,990 --> 00:07:07,300
So error, and then let's just add some emojis
130
130
00:07:07,300 --> 00:07:09,480
so that we know exactly which
131
131
00:07:11,160 --> 00:07:13,173
errors were printed by ourselves.
132
132
00:07:14,760 --> 00:07:17,010
Well, lets add a couple of them here.
133
133
00:07:17,010 --> 00:07:19,950
And in fact, we can actually also style this one
134
134
00:07:19,950 --> 00:07:21,940
with console.error.
135
135
00:07:21,940 --> 00:07:24,170
Remember, I think I showed you this one
136
136
00:07:25,080 --> 00:07:27,960
at some point in the beginning of the course.
137
137
00:07:27,960 --> 00:07:32,180
But anyway, usually simply logging the error to the console
138
138
00:07:32,180 --> 00:07:34,740
is not enough in a real application
139
139
00:07:34,740 --> 00:07:37,110
with a real user interface.
140
140
00:07:37,110 --> 00:07:40,610
And so instead of just logging something to the console
141
141
00:07:40,610 --> 00:07:44,113
let's also display an error message for the user to see.
142
142
00:07:45,640 --> 00:07:49,823
And so that's then a more real use case of this catch block.
143
143
00:07:51,030 --> 00:07:54,700
All right, so I'm adding a new block here
144
144
00:07:54,700 --> 00:07:58,880
so we still want to of course lock the error to the console
145
145
00:07:58,880 --> 00:08:01,973
but besides that let's actually now create a function
146
146
00:08:01,973 --> 00:08:06,973
that will also render some kind of error, okay.
147
147
00:08:07,010 --> 00:08:08,680
So let's do that outside here
148
148
00:08:10,150 --> 00:08:12,103
and I'm calling it renderError.
149
149
00:08:16,660 --> 00:08:20,100
So this is a function and it can take in a message
150
150
00:08:21,180 --> 00:08:23,130
just call it like this.
151
151
00:08:23,130 --> 00:08:24,750
And just like the country elements
152
152
00:08:24,750 --> 00:08:28,123
we want to attach this to countriesContainer
153
153
00:08:29,666 --> 00:08:31,910
and then insert.adjacent.
154
154
00:08:31,910 --> 00:08:36,440
And this time not HTML but insertAdjacent text.
155
155
00:08:36,440 --> 00:08:40,630
So this is a new one but basically it does the same thing
156
156
00:08:41,490 --> 00:08:45,803
as insertAdjacent HTML but simply with text,
157
157
00:08:46,930 --> 00:08:49,473
so it doesn't create any new HTML elements.
158
158
00:08:51,050 --> 00:08:53,700
Okay. And then besides that
159
159
00:08:53,700 --> 00:08:57,893
remember we always have set the opacity back to one.
160
160
00:08:59,110 --> 00:09:03,730
So just as we did before in the render countries function,
161
161
00:09:03,730 --> 00:09:05,900
because otherwise this container
162
162
00:09:05,900 --> 00:09:08,139
is not even gonna be visible.
163
163
00:09:08,139 --> 00:09:09,634
And actually let's put this function
164
164
00:09:09,634 --> 00:09:11,830
right at the very top of the file
165
165
00:09:13,350 --> 00:09:16,323
together with the render country function.
166
166
00:09:20,100 --> 00:09:22,923
So just like this.
167
167
00:09:25,400 --> 00:09:27,910
Okay, so again in both cases
168
168
00:09:27,910 --> 00:09:30,070
in order to actually see the container
169
169
00:09:30,070 --> 00:09:31,963
we set the opacity to one.
170
170
00:09:33,760 --> 00:09:37,030
Okay. And so now here let's use that
171
171
00:09:39,220 --> 00:09:42,513
render, so not country of course Error,
172
172
00:09:44,798 --> 00:09:49,610
let's say something went wrong.
173
173
00:09:49,610 --> 00:09:52,523
Then here we can use our emoji again, why not?
174
174
00:09:54,790 --> 00:09:57,172
And then here let's again print the error
175
175
00:09:57,172 --> 00:10:00,660
and actually this error that is generated here
176
176
00:10:00,660 --> 00:10:03,220
is a real JavaScript object.
177
177
00:10:03,220 --> 00:10:07,210
So we can create errors in JavaScript with a constructor,
178
178
00:10:07,210 --> 00:10:10,113
for example, just like a map or a set.
179
179
00:10:11,260 --> 00:10:15,010
And any error in JavaScript that was created like this
180
180
00:10:15,010 --> 00:10:17,580
contains the message property.
181
181
00:10:17,580 --> 00:10:19,230
So we can use that here
182
182
00:10:20,070 --> 00:10:23,230
to basically only print the message of that error
183
183
00:10:23,230 --> 00:10:26,430
and not the whole object itself.
184
184
00:10:26,430 --> 00:10:28,550
And we will actually learn more about
185
185
00:10:28,550 --> 00:10:32,083
the built in error object of JavaScript in the next video.
186
186
00:10:33,250 --> 00:10:36,810
Now to try this we need to again, get ourselves Online
187
187
00:10:38,960 --> 00:10:42,473
then Offline, check the console.
188
188
00:10:43,380 --> 00:10:47,890
And indeed we get our custom error down here
189
189
00:10:47,890 --> 00:10:49,510
visible by the emojis
190
190
00:10:49,510 --> 00:10:53,060
and then our own message here for the user.
191
191
00:10:53,060 --> 00:10:56,480
Now it's not super pretty but that's not the point here
192
192
00:10:57,550 --> 00:10:59,470
and as you see indeed this here
193
193
00:10:59,470 --> 00:11:01,197
is simply the error.msg.
194
194
00:11:02,180 --> 00:11:05,000
While down here we have the entire error.
195
195
00:11:05,000 --> 00:11:08,050
So that includes the TypeError
196
196
00:11:08,050 --> 00:11:13,050
and even it includes this so-called stack trace
197
197
00:11:13,320 --> 00:11:15,823
so it shows us exactly where the error comes from.
198
198
00:11:17,200 --> 00:11:19,870
All right, and so that's how we handle errors
199
199
00:11:19,870 --> 00:11:24,220
happening in promises in any then handler.
200
200
00:11:24,220 --> 00:11:27,065
So basically handling any promise rejection
201
201
00:11:27,065 --> 00:11:30,390
no matter where it happens in the chain.
202
202
00:11:30,390 --> 00:11:33,300
Now just to finish there is one more quick method
203
203
00:11:33,300 --> 00:11:34,710
that I want to show you
204
204
00:11:34,710 --> 00:11:37,970
and that is also available on all promises.
205
205
00:11:37,970 --> 00:11:42,970
So besides then and catch there is also the finally method.
206
206
00:11:43,550 --> 00:11:48,200
So let's add a finally here, finally.
207
207
00:11:48,200 --> 00:11:51,570
And then the callback function that we defined here
208
208
00:11:51,570 --> 00:11:55,630
will always be called whatever happens with the promise.
209
209
00:11:55,630 --> 00:11:59,860
So no matter if the promise is fulfilled or rejected
210
210
00:11:59,860 --> 00:12:01,902
this callback function that we define here
211
211
00:12:01,902 --> 00:12:04,970
is gonna be called always.
212
212
00:12:04,970 --> 00:12:07,740
So that's the difference between the other two
213
213
00:12:07,740 --> 00:12:10,150
so the then method is only called
214
214
00:12:10,150 --> 00:12:13,610
when the promise is fulfilled while this one is only called
215
215
00:12:13,610 --> 00:12:16,550
while the promise is rejected.
216
216
00:12:16,550 --> 00:12:20,000
Now the finally method is not always useful,
217
217
00:12:20,000 --> 00:12:22,170
but sometimes it actually is.
218
218
00:12:22,170 --> 00:12:23,700
So we use this method
219
219
00:12:23,700 --> 00:12:26,210
for something that always needs to happen
220
220
00:12:26,210 --> 00:12:29,120
no matter the result of the promise.
221
221
00:12:29,120 --> 00:12:33,080
And one good example of that is to hide a loading spinner
222
222
00:12:33,080 --> 00:12:36,200
like these rotating circles that you see everywhere
223
223
00:12:36,200 --> 00:12:39,570
in web applications when you load some data.
224
224
00:12:39,570 --> 00:12:42,070
So these applications show a spinner
225
225
00:12:42,070 --> 00:12:44,750
when an asynchronous operation starts
226
226
00:12:44,750 --> 00:12:47,780
and then hide it once the operation completes.
227
227
00:12:47,780 --> 00:12:49,520
And that happens no matter
228
228
00:12:49,520 --> 00:12:52,690
if the operation was successfully or not.
229
229
00:12:52,690 --> 00:12:56,520
And so for that to finally method is perfect.
230
230
00:12:56,520 --> 00:12:59,180
And in our case, what we always need to do
231
231
00:12:59,180 --> 00:13:01,570
is to fade-in the container.
232
232
00:13:01,570 --> 00:13:05,420
So, basically this part here
233
233
00:13:05,420 --> 00:13:08,810
always happens no matter what, right?
234
234
00:13:08,810 --> 00:13:10,860
So no matter if we render the country
235
235
00:13:10,860 --> 00:13:12,160
in the case of success
236
236
00:13:12,160 --> 00:13:16,110
or if we render the error in case of an error,
237
237
00:13:16,110 --> 00:13:19,080
no matter what we always need to do this.
238
238
00:13:19,080 --> 00:13:21,349
And so let's take this out of here,
239
239
00:13:21,349 --> 00:13:23,020
so I'm copying it here
240
240
00:13:24,590 --> 00:13:28,450
and deactivating this in both cases
241
241
00:13:28,450 --> 00:13:33,450
and then let's put it here into the finally handler, okay.
242
242
00:13:33,810 --> 00:13:36,600
And now we no longer need the Offline
243
243
00:13:37,730 --> 00:13:41,610
so let's just reload, put it here
244
244
00:13:41,610 --> 00:13:44,053
and yeah that works beautifully.
245
245
00:13:45,186 --> 00:13:50,020
Just notice that this actually works because catch itself
246
246
00:13:50,020 --> 00:13:52,050
also returns a promise.
247
247
00:13:52,050 --> 00:13:55,360
So that's the only way why this here can work
248
248
00:13:55,360 --> 00:13:58,700
so of course this only works on promises.
249
249
00:13:58,700 --> 00:14:01,770
And so, yeah, again, this can only work
250
250
00:14:01,770 --> 00:14:05,193
if catch itself also returns a promise.
251
251
00:14:07,030 --> 00:14:11,070
All right, now let's try to simulate another error
252
252
00:14:11,070 --> 00:14:13,923
so that I can show you what we need to do next.
253
253
00:14:14,810 --> 00:14:18,050
So let's say that we're trying to search for a country
254
254
00:14:18,050 --> 00:14:20,050
that simply doesn't exist.
255
255
00:14:20,050 --> 00:14:24,420
And so, or API is not gonna find any result for that.
256
256
00:14:24,420 --> 00:14:28,459
Let's say just this, so let's see.
257
257
00:14:28,459 --> 00:14:31,363
And well we get to this weird error
258
258
00:14:31,363 --> 00:14:36,363
that we Cannot read property flag of undefined in line 152.
259
259
00:14:38,320 --> 00:14:41,731
Now, so basically it's coming from this place
260
260
00:14:41,731 --> 00:14:44,570
but of course then in stack trace
261
261
00:14:44,570 --> 00:14:47,670
we can see where exactly it's coming from,
262
262
00:14:47,670 --> 00:14:50,043
so it's coming from getCountryData.
263
263
00:14:51,600 --> 00:14:53,930
Well, in this case it's not that helpful
264
264
00:14:53,930 --> 00:14:57,050
but sometimes inspecting this stack trace
265
265
00:14:57,050 --> 00:14:59,443
can be helpful indeed.
266
266
00:15:00,520 --> 00:15:03,310
So anyway, this error here is weird
267
267
00:15:03,310 --> 00:15:05,900
and it doesn't really reflect the true error
268
268
00:15:05,900 --> 00:15:07,940
which is simply that our API
269
269
00:15:07,940 --> 00:15:11,200
cannot find any country with this name.
270
270
00:15:11,200 --> 00:15:13,493
So the true error is of course not
271
271
00:15:13,493 --> 00:15:16,267
that we Cannot read flag of undefined
272
272
00:15:16,267 --> 00:15:21,267
but in fact it is that our API cannot find any country.
273
273
00:15:21,400 --> 00:15:26,100
And so that's reflected here with the status code 404.
274
274
00:15:26,100 --> 00:15:28,120
However, as I said in the beginning
275
275
00:15:28,120 --> 00:15:30,190
the fetch promise only rejects
276
276
00:15:30,190 --> 00:15:32,800
when there is no internet connection,
277
277
00:15:32,800 --> 00:15:37,272
but with a 404 error like this which is not a real error
278
278
00:15:37,272 --> 00:15:39,960
but well it kind of is.
279
279
00:15:39,960 --> 00:15:43,560
But anyway with this 404 the fetch promise
280
280
00:15:43,560 --> 00:15:45,710
will still get fulfilled.
281
281
00:15:45,710 --> 00:15:48,926
So there is no rejection and so our catch handler
282
282
00:15:48,926 --> 00:15:52,030
cannot pick up on this error.
283
283
00:15:52,030 --> 00:15:56,530
It does pick up on this other error so in this one here,
284
284
00:15:56,530 --> 00:15:59,580
but that's not the one that we actually want to handle.
285
285
00:15:59,580 --> 00:16:01,860
In this case we really want to tell the user
286
286
00:16:01,860 --> 00:16:05,370
that no country was found with this name.
287
287
00:16:05,370 --> 00:16:08,290
And so that is what we will do in the next lecture,
288
288
00:16:08,290 --> 00:16:10,963
so that this one doesn't become all too long.
25320
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.