1
00:00:02,130 --> 00:00:04,340
Now that we had a look behind the scenes

2
00:00:04,340 --> 00:00:08,010
and had a look at the more difficult parts of JavaScript,

3
00:00:08,010 --> 00:00:10,320
let's come back to something simpler.

4
00:00:10,320 --> 00:00:13,403
Let's come back to error handling.

5
00:00:13,403 --> 00:00:14,236
For this here,

6
00:00:14,236 --> 00:00:19,040
I'm back in that project we worked on before in Express.

7
00:00:19,040 --> 00:00:23,700
And you might remember that there, something could go wrong.

8
00:00:23,700 --> 00:00:27,350
If we try to read or write to this restaurants.json file,

9
00:00:27,350 --> 00:00:28,690
and I rename it

10
00:00:28,690 --> 00:00:31,790
to simulate that it's currently not available,

11
00:00:31,790 --> 00:00:33,890
then we got an error.

12
00:00:33,890 --> 00:00:35,338
And we handled that

13
00:00:35,338 --> 00:00:38,960
with that default error-handling middleware here

14
00:00:38,960 --> 00:00:43,300
which allowed us to send back this 500 status code

15
00:00:43,300 --> 00:00:45,770
and this 500 page.

16
00:00:45,770 --> 00:00:49,260
That's what we saw before in this course.

17
00:00:49,260 --> 00:00:52,140
Now, that was a really useful pattern

18
00:00:52,140 --> 00:00:53,940
because it allowed us to ensure

19
00:00:53,940 --> 00:00:56,240
that we sent back some response

20
00:00:56,240 --> 00:01:00,190
even if something went wrong on our server.

21
00:01:00,190 --> 00:01:04,010
But this is not necessarily always the best way

22
00:01:04,010 --> 00:01:06,230
of handling such scenarios.

23
00:01:06,230 --> 00:01:09,960
It was fine here, but the more complex your code gets,

24
00:01:09,960 --> 00:01:12,920
the more actions you might want to execute

25
00:01:12,920 --> 00:01:14,920
in your route handlers,

26
00:01:14,920 --> 00:01:18,820
the less optimal this approach could get.

27
00:01:18,820 --> 00:01:22,090
And therefore, I'm back in that simpler project

28
00:01:22,090 --> 00:01:24,680
or this simpler demo workspace

29
00:01:24,680 --> 00:01:27,400
we worked in this course section.

30
00:01:27,400 --> 00:01:29,583
Here I'll add a new file, errors.js.

31
00:01:30,930 --> 00:01:33,530
And in there I will write some code

32
00:01:33,530 --> 00:01:36,570
that will only run on Node.js now

33
00:01:36,570 --> 00:01:38,010
because it makes it a bit easier

34
00:01:38,010 --> 00:01:39,890
for me to show you what I mean,

35
00:01:39,890 --> 00:01:43,930
though the error-handling approach I'm about to show you

36
00:01:43,930 --> 00:01:47,683
would also work on the frontend, in the browser side.

37
00:01:48,590 --> 00:01:52,810
Now, here I'll again require the file system package,

38
00:01:52,810 --> 00:01:56,710
and that's the part that only works here in Node.js

39
00:01:56,710 --> 00:02:00,560
because that is not code that would work in the browser.

40
00:02:00,560 --> 00:02:04,820
The browser would neither understand this require function

41
00:02:04,820 --> 00:02:09,470
nor do you have access to some file system in the browser.

42
00:02:09,470 --> 00:02:11,260
But the rest of the code which I'll write

43
00:02:11,260 --> 00:02:13,720
would work the same way in the browser

44
00:02:13,720 --> 00:02:15,993
if we leave out the file system part.

45
00:02:17,380 --> 00:02:20,317
And here I'll add a new function, readFile,

46
00:02:21,760 --> 00:02:25,710
and in that function I will now call readFileSync

47
00:02:25,710 --> 00:02:28,020
as I did it before in this course,

48
00:02:28,020 --> 00:02:31,430
and I'll try to read the data.json file

49
00:02:31,430 --> 00:02:34,360
which doesn't exist here.

50
00:02:34,360 --> 00:02:37,550
There is no data.json file in this project,

51
00:02:37,550 --> 00:02:39,343
so this line of code should fail.

52
00:02:40,630 --> 00:02:44,330
Now, I would get my file data here

53
00:02:44,330 --> 00:02:46,740
as a result of calling readFileSync,

54
00:02:46,740 --> 00:02:48,363
but, again, this will fail.

55
00:02:49,220 --> 00:02:53,810
Now, let's say I thereafter have another step

56
00:02:53,810 --> 00:02:57,260
where I output something totally else,

57
00:02:57,260 --> 00:03:00,070
something like Hi there! as a placeholder,

58
00:03:00,070 --> 00:03:01,250
but, of course, we could be doing

59
00:03:01,250 --> 00:03:03,260
something more useful here.

60
00:03:03,260 --> 00:03:05,650
We could be storing some data in a database

61
00:03:05,650 --> 00:03:09,250
or do anything else that's not directly related

62
00:03:09,250 --> 00:03:10,793
to reading that file.

63
00:03:12,550 --> 00:03:16,560
Now, if we execute readFile here,

64
00:03:16,560 --> 00:03:18,460
that, of course, will fail,

65
00:03:18,460 --> 00:03:20,090
as I mentioned.

66
00:03:20,090 --> 00:03:25,090
If I execute errors.js, we get an error.

67
00:03:27,820 --> 00:03:30,810
Now, this is not an Express application here.

68
00:03:30,810 --> 00:03:33,550
It's just some standard Node code,

69
00:03:33,550 --> 00:03:35,540
some standard JavaScript code

70
00:03:35,540 --> 00:03:38,850
executed with Node using a Node feature.

71
00:03:38,850 --> 00:03:41,030
But, of course, this could be inside

72
00:03:41,030 --> 00:03:42,950
of an Express application.

73
00:03:42,950 --> 00:03:45,950
And if it would be inside of that application,

74
00:03:45,950 --> 00:03:49,770
we could, again, use that error-handling middleware

75
00:03:49,770 --> 00:03:53,420
to send back a default error response.

76
00:03:53,420 --> 00:03:57,750
The problem just is that if we follow this approach,

77
00:03:57,750 --> 00:04:01,270
as soon as this line of code fails here,

78
00:04:01,270 --> 00:04:03,930
this function execution would stop

79
00:04:03,930 --> 00:04:06,030
because if an error occurs,

80
00:04:06,030 --> 00:04:09,550
by default, the function in which that error occurred

81
00:04:09,550 --> 00:04:11,960
will stop executing,

82
00:04:11,960 --> 00:04:14,610
and that error will be passed

83
00:04:14,610 --> 00:04:18,029
to the place where the function was called.

84
00:04:18,029 --> 00:04:20,209
And in Express case,

85
00:04:20,209 --> 00:04:24,560
Express is the thing calling our route handler functions.

86
00:04:24,560 --> 00:04:27,870
And if it receives an error by one of the route handlers,

87
00:04:27,870 --> 00:04:29,530
it therefore then executes

88
00:04:29,530 --> 00:04:32,070
that default error-handling middleware

89
00:04:32,070 --> 00:04:33,980
because it sees there was an error,

90
00:04:33,980 --> 00:04:36,480
and it then executes that middleware.

91
00:04:36,480 --> 00:04:39,310
Here we are calling that function,

92
00:04:39,310 --> 00:04:41,480
and we're not doing anything with that error,

93
00:04:41,480 --> 00:04:43,770
and hence everything fails here.

94
00:04:43,770 --> 00:04:45,670
But that's not the main problem.

95
00:04:45,670 --> 00:04:49,000
The main problem is that even with Express,

96
00:04:49,000 --> 00:04:52,050
we might get that default error handler,

97
00:04:52,050 --> 00:04:54,730
but what if we actually don't want

98
00:04:54,730 --> 00:04:56,940
to stop executing this function

99
00:04:56,940 --> 00:04:59,413
just because this line failed?

100
00:05:00,480 --> 00:05:03,620
Because in programming, it's not always the case

101
00:05:03,620 --> 00:05:06,280
that you wanna throw away everything

102
00:05:06,280 --> 00:05:08,500
and stop executing everything

103
00:05:08,500 --> 00:05:11,540
just because you encounter some error.

104
00:05:11,540 --> 00:05:15,790
You might have a plan B. You might be able to recover.

105
00:05:15,790 --> 00:05:20,790
Or maybe the operation that failed wasn't that important.

106
00:05:20,810 --> 00:05:25,070
Maybe that very next line is super important though.

107
00:05:25,070 --> 00:05:28,560
Here we are just console.logging, but as I said before,

108
00:05:28,560 --> 00:05:31,100
maybe we are writing to a database here.

109
00:05:31,100 --> 00:05:33,840
So that could be a super important operation

110
00:05:33,840 --> 00:05:35,630
which we don't wanna skip

111
00:05:35,630 --> 00:05:38,483
just because this line failed here.

112
00:05:39,570 --> 00:05:42,220
And because you have scenarios like this,

113
00:05:42,220 --> 00:05:44,120
and you have them quite often,

114
00:05:44,120 --> 00:05:49,120
we can also wrap this line here which might fail

115
00:05:49,150 --> 00:05:51,320
with an extra construct

116
00:05:51,320 --> 00:05:56,113
that exists in both browser side and Node.js JavaScript.

117
00:05:56,950 --> 00:06:00,123
We can wrap it with try curly braces.

118
00:06:01,700 --> 00:06:03,410
If we do that,

119
00:06:03,410 --> 00:06:08,300
then JavaScript will try to execute this code here

120
00:06:08,300 --> 00:06:10,240
between those curly braces.

121
00:06:10,240 --> 00:06:12,410
And if that should fail,

122
00:06:12,410 --> 00:06:15,330
we can catch the error that occurred

123
00:06:15,330 --> 00:06:18,220
and handle it in any way we want.

124
00:06:18,220 --> 00:06:22,360
And for this, we add another part to this try statement.

125
00:06:22,360 --> 00:06:24,250
We add the catch keyword

126
00:06:24,250 --> 00:06:26,973
and then another part of curly braces.

127
00:06:28,260 --> 00:06:33,040
And here we now put our code that will run

128
00:06:33,040 --> 00:06:36,363
if the code in the try block failed.

129
00:06:37,720 --> 00:06:41,500
With that, we can now add our own error handling

130
00:06:41,500 --> 00:06:45,173
inside of the function where the error occurred.

131
00:06:46,130 --> 00:06:48,130
So instead of then just escalating it

132
00:06:48,130 --> 00:06:51,670
to the place where we called readFile,

133
00:06:51,670 --> 00:06:54,150
so instead of just passing on the error

134
00:06:54,150 --> 00:06:55,810
to that line of code,

135
00:06:55,810 --> 00:06:59,360
we handle it directly inside this function,

136
00:06:59,360 --> 00:07:03,070
and the code thereafter will execute just fine

137
00:07:03,070 --> 00:07:06,360
because now that error is handled,

138
00:07:06,360 --> 00:07:09,290
and the function will not stop executing

139
00:07:09,290 --> 00:07:11,983
because we're using try-catch.

140
00:07:14,020 --> 00:07:16,310
And if I now save this,

141
00:07:16,310 --> 00:07:18,810
and I execute errors.js,

142
00:07:18,810 --> 00:07:21,100
you see we get an error occurred,

143
00:07:21,100 --> 00:07:24,340
which is that error-handling code we wrote here,

144
00:07:24,340 --> 00:07:28,563
so that's where this message here is coming from.

145
00:07:30,270 --> 00:07:33,307
And then we see Hi there!,

146
00:07:34,180 --> 00:07:37,420
which is this line of code which executes just fine

147
00:07:37,420 --> 00:07:40,420
because the overall function execution of readFile

148
00:07:40,420 --> 00:07:42,253
was not stopped.

149
00:07:43,530 --> 00:07:47,410
And therefore, try-catch is a very useful construct

150
00:07:47,410 --> 00:07:51,250
for handling errors that might occur on your own

151
00:07:51,250 --> 00:07:53,350
with great detail

152
00:07:53,350 --> 00:07:58,190
instead of relying on general error-handling mechanisms.

153
00:07:58,190 --> 00:08:01,520
Those general mechanisms can still be useful,

154
00:08:01,520 --> 00:08:03,520
but often you can also combine them

155
00:08:03,520 --> 00:08:06,750
with fine-grained, custom error handling

156
00:08:06,750 --> 00:08:10,990
where you maybe retry the operation first

157
00:08:10,990 --> 00:08:15,670
before reaching out to a general error-handling mechanism,

158
00:08:15,670 --> 00:08:19,170
or where you maybe create your own object

159
00:08:19,170 --> 00:08:20,830
describing the error

160
00:08:20,830 --> 00:08:23,870
which you then use in your application.

161
00:08:23,870 --> 00:08:26,520
There are a lot of ways of using try-catch,

162
00:08:26,520 --> 00:08:29,760
and you'll see try-catch being used throughout the course,

163
00:08:29,760 --> 00:08:31,830
hence it's important to introduce

164
00:08:31,830 --> 00:08:33,513
and understand it right now.

165
00:08:35,260 --> 00:08:38,250
Now, of course, when you learn about try-catch,

166
00:08:38,250 --> 00:08:40,690
one obvious question that might come up

167
00:08:40,690 --> 00:08:45,690
is why don't we wrap all our code with try-catch?

168
00:08:47,370 --> 00:08:50,930
And there are a couple of reasons for not doing that.

169
00:08:50,930 --> 00:08:53,430
For one, if you wrap everything,

170
00:08:53,430 --> 00:08:56,230
you will also catch a couple of errors

171
00:08:56,230 --> 00:08:59,100
that should indeed crash your application

172
00:08:59,100 --> 00:09:00,900
because they are simply bugs

173
00:09:00,900 --> 00:09:03,500
which you can fix during development,

174
00:09:03,500 --> 00:09:06,060
so which you as a developer should see

175
00:09:06,060 --> 00:09:08,730
whilst you are writing your code.

176
00:09:08,730 --> 00:09:10,800
And if you try and handle them,

177
00:09:10,800 --> 00:09:13,853
you might not spot those errors that quickly.

178
00:09:14,880 --> 00:09:19,000
Another reason for not wrapping everything with try-catch

179
00:09:19,000 --> 00:09:23,340
is that different errors that stem from different sources

180
00:09:23,340 --> 00:09:26,650
often should be handled in different ways.

181
00:09:26,650 --> 00:09:29,990
An error that stems from reading a file

182
00:09:29,990 --> 00:09:32,330
should maybe be handled differently

183
00:09:32,330 --> 00:09:34,830
than an error we might be getting

184
00:09:34,830 --> 00:09:38,450
when we try to get data from a database.

185
00:09:38,450 --> 00:09:40,440
When we fail to read a file,

186
00:09:40,440 --> 00:09:44,790
we might want to retry this after a second or so.

187
00:09:44,790 --> 00:09:47,770
So we might wanna handle this in a different way.

188
00:09:47,770 --> 00:09:49,650
And that's why we don't want

189
00:09:49,650 --> 00:09:52,300
to wrap everything with try-catch,

190
00:09:52,300 --> 00:09:56,190
but only the places where we can expect errors

191
00:09:56,190 --> 00:09:58,200
in some circumstances

192
00:09:58,200 --> 00:10:02,130
and then only as little code as necessary.

193
00:10:02,130 --> 00:10:05,180
That's how you should use try-catch.

194
00:10:05,180 --> 00:10:07,190
But, again, you'll see plenty of examples

195
00:10:07,190 --> 00:10:10,243
of try-catch in action throughout this course.

