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