﻿1
00:00:01,100 --> 00:00:02,750
‫In this video, let's now create

2
00:00:02,750 --> 00:00:05,470
‫a better and more useful error class,

3
00:00:05,470 --> 00:00:07,373
‫and also do some refactoring.

4
00:00:09,210 --> 00:00:11,870
‫And starting with that error class,

5
00:00:11,870 --> 00:00:15,053
‫let's create a new file in our Utilities folder.

6
00:00:15,950 --> 00:00:18,990
‫So, new file, and I'm going to call it AppError

7
00:00:20,980 --> 00:00:25,820
‫because that's going to be the name of the class, all right?

8
00:00:25,820 --> 00:00:30,820
‫So, class AppError, and we actually want all of our

9
00:00:30,867 --> 00:00:34,780
‫AppError objects to then inherit from the built-in error,

10
00:00:34,780 --> 00:00:39,260
‫and so let's actually extend the built-in error class.

11
00:00:39,260 --> 00:00:43,720
‫So, we used extends Error, okay?

12
00:00:43,720 --> 00:00:46,870
‫So, we did that before somewhere in this course,

13
00:00:46,870 --> 00:00:50,950
‫and again this is just ES6 classes, all right?

14
00:00:50,950 --> 00:00:52,920
‫In this case, class inheritance,

15
00:00:52,920 --> 00:00:56,790
‫where one class inherits from the other, okay?

16
00:00:56,790 --> 00:00:59,300
‫Then, as always, our constructor,

17
00:00:59,300 --> 00:01:01,800
‫and what we're going to pass into a new object

18
00:01:01,800 --> 00:01:04,490
‫created from the AppError class is going to be

19
00:01:04,490 --> 00:01:08,660
‫the message and the statusCode,

20
00:01:08,660 --> 00:01:09,853
‫so just these two.

21
00:01:11,330 --> 00:01:15,130
‫Okay, so, remember the constructor method is called

22
00:01:15,130 --> 00:01:19,210
‫each time that we create a new object out of this class.

23
00:01:19,210 --> 00:01:22,116
‫Now, as usual, when we extend a parent class,

24
00:01:22,116 --> 00:01:25,760
‫we call super in order to call

25
00:01:25,760 --> 00:01:28,203
‫the parent constructor, all right,

26
00:01:30,100 --> 00:01:33,580
‫and we do that with message because the message is actually

27
00:01:33,580 --> 00:01:37,160
‫the only parameter that the built-in error accepts.

28
00:01:37,160 --> 00:01:40,990
‫Okay, so this is basically you're, like, calling error,

29
00:01:40,990 --> 00:01:44,305
‫all right, and then this is here is the usual stuff,

30
00:01:44,305 --> 00:01:46,160
‫we set the statusCode

31
00:01:48,300 --> 00:01:53,030
‫to statusCode, all right,

32
00:01:53,030 --> 00:01:56,463
‫and now we also want to set the status itself.

33
00:01:58,200 --> 00:02:01,670
‫So, remember the status can either be fail or error,

34
00:02:01,670 --> 00:02:03,920
‫and we could pass that into the object,

35
00:02:03,920 --> 00:02:05,700
‫but it's also not really necessary,

36
00:02:05,700 --> 00:02:08,530
‫because the status depends on the statusCode.

37
00:02:08,530 --> 00:02:10,880
‫So, when the statusCode is a 400,

38
00:02:10,880 --> 00:02:12,630
‫then the status will be fail,

39
00:02:12,630 --> 00:02:16,230
‫and if it's a 500, then it's going to be an error, right,

40
00:02:16,230 --> 00:02:18,336
‫and so that simply tests if the

41
00:02:18,336 --> 00:02:20,420
‫statusCode starts with a four.

42
00:02:20,420 --> 00:02:23,800
‫So, in JavaScript, there is a startsWith method

43
00:02:23,800 --> 00:02:25,540
‫that we can call on strings,

44
00:02:25,540 --> 00:02:28,100
‫and so I think that's the easiest way of doing this test,

45
00:02:28,100 --> 00:02:31,363
‫and so that's basically convert the statusCode to a string,

46
00:02:32,780 --> 00:02:35,610
‫and for that I'm simply using a template string with

47
00:02:35,610 --> 00:02:38,030
‫the code in there, so this,

48
00:02:38,030 --> 00:02:40,380
‫or actually we can just use statusCode.

49
00:02:41,781 --> 00:02:42,614
‫So, statusCode, and then startsWith,

50
00:02:47,001 --> 00:02:48,750
‫then here we also need a string,

51
00:02:48,750 --> 00:02:51,120
‫and so if the statusCode as a string

52
00:02:51,120 --> 00:02:54,330
‫starts with a four, well, then we have a fail.

53
00:02:54,330 --> 00:02:58,360
‫And so here, let's use the ternary, okay,

54
00:02:58,360 --> 00:03:02,120
‫and so it's fail when it starts with a four,

55
00:03:02,120 --> 00:03:06,890
‫and otherwise it's an error, okay?

56
00:03:06,890 --> 00:03:09,550
‫So, very simple, and this already saves us

57
00:03:09,550 --> 00:03:13,250
‫from manually have to pass in either fail or error.

58
00:03:13,250 --> 00:03:15,240
‫All right, now next up,

59
00:03:15,240 --> 00:03:17,120
‫all the errors that we will create

60
00:03:17,120 --> 00:03:20,300
‫using this class will all be operational errors.

61
00:03:20,300 --> 00:03:22,070
‫So, errors that we can predict

62
00:03:22,070 --> 00:03:24,130
‫will happen in some point in the future,

63
00:03:24,130 --> 00:03:26,010
‫like for example a user creating

64
00:03:26,010 --> 00:03:29,560
‫a tour without the required fields, right?

65
00:03:29,560 --> 00:03:32,380
‫So that is an operational error, okay,

66
00:03:32,380 --> 00:03:34,660
‫and so again, from now on, we will

67
00:03:34,660 --> 00:03:37,125
‫always use this AppError class here

68
00:03:37,125 --> 00:03:39,070
‫that we're creating right now

69
00:03:39,070 --> 00:03:42,230
‫in order to create all the errors in our application.

70
00:03:42,230 --> 00:03:44,730
‫And so these errors will be operational errors,

71
00:03:44,730 --> 00:03:46,250
‫and so what I'm gonna do now is

72
00:03:46,250 --> 00:03:49,663
‫to actually also create a .is operational property here.

73
00:03:50,980 --> 00:03:53,133
‫So this.is operational,

74
00:03:56,100 --> 00:03:57,380
‫and set it to true.

75
00:03:57,380 --> 00:03:59,240
‫So all of our errors will

76
00:03:59,240 --> 00:04:01,680
‫get this property set to true,

77
00:04:01,680 --> 00:04:03,420
‫and I'm doing that so that later

78
00:04:03,420 --> 00:04:05,890
‫we can then test for this property

79
00:04:05,890 --> 00:04:07,910
‫and only send error messages back

80
00:04:07,910 --> 00:04:10,360
‫to the client for these operational errors

81
00:04:10,360 --> 00:04:12,510
‫that we created using this class.

82
00:04:12,510 --> 00:04:14,550
‫And this is useful because some other

83
00:04:14,550 --> 00:04:17,210
‫crazy unexpected errors that might happen

84
00:04:17,210 --> 00:04:19,964
‫in our application, for example a programming error,

85
00:04:19,964 --> 00:04:22,360
‫or some bug in one of the packages

86
00:04:22,360 --> 00:04:24,550
‫that we require into our app,

87
00:04:24,550 --> 00:04:26,100
‫and these errors will then of course

88
00:04:26,100 --> 00:04:29,610
‫not have this .is operational property on them,

89
00:04:29,610 --> 00:04:31,610
‫all right, and it might sound

90
00:04:31,610 --> 00:04:33,370
‫a bit confusing at this point,

91
00:04:33,370 --> 00:04:35,220
‫but don't worry, it will make

92
00:04:35,220 --> 00:04:37,040
‫a lot of sense when we then

93
00:04:37,040 --> 00:04:39,860
‫implement that part that I just mentioned.

94
00:04:39,860 --> 00:04:43,740
‫So, testing for this .is operational property here.

95
00:04:43,740 --> 00:04:46,190
‫All right, and now just one last step

96
00:04:46,190 --> 00:04:50,270
‫is that we actually also need to capture the stack trace.

97
00:04:50,270 --> 00:04:53,090
‫Now, what do I mean by stack trace?

98
00:04:53,090 --> 00:04:55,430
‫And so, let me actually show that to you,

99
00:04:55,430 --> 00:04:58,380
‫so, show you what stack trace is,

100
00:04:58,380 --> 00:05:01,093
‫and so I will log it here to the console.

101
00:05:02,180 --> 00:05:05,053
‫Console.log and error.stackTrace,

102
00:05:06,390 --> 00:05:10,350
‫so each and every error gets this stack trace,

103
00:05:10,350 --> 00:05:13,370
‫and actually it's just stack, okay.

104
00:05:13,370 --> 00:05:15,820
‫So err.stack will basically

105
00:05:15,820 --> 00:05:17,743
‫show us where the error happened.

106
00:05:19,320 --> 00:05:20,743
‫So let me run this here now,

107
00:05:22,450 --> 00:05:24,303
‫and so let's take a look at this,

108
00:05:26,420 --> 00:05:28,000
‫and so it gives us here the error

109
00:05:28,000 --> 00:05:31,290
‫and then also where it happened, okay?

110
00:05:31,290 --> 00:05:33,040
‫So, in this case here, of course,

111
00:05:33,040 --> 00:05:36,390
‫add app.js at line 32.

112
00:05:36,390 --> 00:05:38,810
‫So, right here.

113
00:05:38,810 --> 00:05:40,470
‫So, that's where we created this error,

114
00:05:40,470 --> 00:05:42,200
‫and so it's now in our stack trace,

115
00:05:42,200 --> 00:05:44,972
‫and it also shows us the entire call stack here,

116
00:05:44,972 --> 00:05:49,972
‫which in the end the originated in this error, okay?

117
00:05:50,400 --> 00:05:52,440
‫So we kind of want to preserve that

118
00:05:52,440 --> 00:05:56,500
‫and also at the same time not add this method here,

119
00:05:56,500 --> 00:06:00,390
‫or this class, to that stack track, okay?

120
00:06:00,390 --> 00:06:02,350
‫And again, that sounds a bit confusing,

121
00:06:02,350 --> 00:06:03,980
‫I know, but in this case

122
00:06:03,980 --> 00:06:06,359
‫it's not really important, all that matters

123
00:06:06,359 --> 00:06:09,100
‫is that we just add this line of code here,

124
00:06:09,100 --> 00:06:11,873
‫which is Error.capturestackTrace,

125
00:06:13,670 --> 00:06:16,160
‫so exactly what you get here,

126
00:06:16,160 --> 00:06:19,490
‫and at first we need to specify the current object,

127
00:06:19,490 --> 00:06:23,530
‫which is this, and then the AppError class itself,

128
00:06:23,530 --> 00:06:26,113
‫which is gonna be this.constructor.

129
00:06:28,340 --> 00:06:31,220
‫Okay, and so this way when a new object

130
00:06:31,220 --> 00:06:34,361
‫is created, and a constructor function is called,

131
00:06:34,361 --> 00:06:36,388
‫then that function call is not gonna appear

132
00:06:36,388 --> 00:06:38,863
‫in the stack trace, and will not pollute it.

133
00:06:40,240 --> 00:06:41,073
‫All right,

134
00:06:42,250 --> 00:06:44,920
‫so let's put it down here,

135
00:06:44,920 --> 00:06:48,280
‫and yeah, so that's our AppError class,

136
00:06:48,280 --> 00:06:51,363
‫and so let's now actually export it from here.

137
00:06:52,450 --> 00:06:56,443
‫So, module.exports is of course the AppError.

138
00:06:57,340 --> 00:07:00,367
‫Great, just one question that you might have is

139
00:07:00,367 --> 00:07:04,720
‫'Why didn't I set this.message equal to message?'

140
00:07:04,720 --> 00:07:07,600
‫Well, that's just because right here I called

141
00:07:07,600 --> 00:07:10,253
‫the parent class, right, and the parent class

142
00:07:10,253 --> 00:07:13,380
‫is error, and whatever we pass into it

143
00:07:13,380 --> 00:07:15,350
‫is gonna be the message property.

144
00:07:15,350 --> 00:07:16,860
‫So just as I told you before.

145
00:07:16,860 --> 00:07:20,880
‫And so, basically, in here by doing this parent call

146
00:07:20,880 --> 00:07:22,890
‫we already set the message property

147
00:07:22,890 --> 00:07:24,463
‫to our incoming message.

148
00:07:25,970 --> 00:07:28,500
‫All right, give it a save, and now we can close it,

149
00:07:28,500 --> 00:07:29,653
‫we no longer need it,

150
00:07:30,770 --> 00:07:32,933
‫and here we're just gonna import it here.

151
00:07:34,621 --> 00:07:35,871
‫Const AppError,

152
00:07:38,980 --> 00:07:39,883
‫require,

153
00:07:41,560 --> 00:07:43,600
‫and then it's in utils,

154
00:07:43,600 --> 00:07:48,320
‫so Utilities, and appError, okay,

155
00:07:48,320 --> 00:07:51,423
‫and so now let's actually go ahead and use it.

156
00:07:53,280 --> 00:07:55,070
‫Comment out this piece of code,

157
00:07:55,070 --> 00:07:57,420
‫and actually delete the one that we had before,

158
00:07:58,860 --> 00:08:00,210
‫and that will now create the error

159
00:08:00,210 --> 00:08:02,650
‫right here inside of next.

160
00:08:02,650 --> 00:08:04,433
‫So, new AppError,

161
00:08:06,600 --> 00:08:07,783
‫and then the message,

162
00:08:09,430 --> 00:08:10,793
‫which is this one,

163
00:08:12,910 --> 00:08:14,023
‫and the status code.

164
00:08:15,620 --> 00:08:18,410
‫Right, and the fail, remember, will then automatically

165
00:08:18,410 --> 00:08:22,480
‫be figured out, and so let's delete all of this,

166
00:08:22,480 --> 00:08:23,723
‫give it a save here,

167
00:08:25,320 --> 00:08:29,630
‫and one more time, test out this wrong route,

168
00:08:29,630 --> 00:08:32,940
‫and indeed we still get our same error,

169
00:08:32,940 --> 00:08:37,530
‫and we also still get our exact same stack trace.

170
00:08:37,530 --> 00:08:40,280
‫Okay, and finally I actually also want

171
00:08:40,280 --> 00:08:43,550
‫to export this middleware here, okay?

172
00:08:43,550 --> 00:08:45,260
‫So basically, this handler

173
00:08:45,260 --> 00:08:47,150
‫because throughout the rest of the section,

174
00:08:47,150 --> 00:08:48,760
‫we're gonna build a couple of different

175
00:08:48,760 --> 00:08:51,700
‫functions for handling with different types of errors,

176
00:08:51,700 --> 00:08:53,280
‫and so I want all of these functions

177
00:08:53,280 --> 00:08:55,912
‫to be all in the same file, all right?

178
00:08:55,912 --> 00:08:58,920
‫And we can say that all of these functions

179
00:08:58,920 --> 00:09:02,310
‫that I just mentioned are handlers, okay,

180
00:09:02,310 --> 00:09:05,320
‫and so handlers, we also call them controllers

181
00:09:05,320 --> 00:09:08,240
‫in the context of the MVC architecture,

182
00:09:08,240 --> 00:09:10,130
‫and so let's now actually create

183
00:09:10,130 --> 00:09:13,253
‫an error controller file in our controller folder.

184
00:09:14,190 --> 00:09:18,280
‫Okay, and this might sound or look a bit weird

185
00:09:18,280 --> 00:09:21,330
‫because we actually do not have an error resource

186
00:09:22,200 --> 00:09:24,940
‫okay, and so probably some people are gonna disagree

187
00:09:24,940 --> 00:09:26,923
‫with me that this is the correct place,

188
00:09:28,540 --> 00:09:31,100
‫but I personally like to do it like this

189
00:09:31,100 --> 00:09:32,520
‫because at the end of the day,

190
00:09:32,520 --> 00:09:34,910
‫these functions, they kinda are like

191
00:09:34,910 --> 00:09:37,370
‫really for controlling our errors, all right,

192
00:09:37,370 --> 00:09:39,570
‫and so for me at least it makes sense

193
00:09:39,570 --> 00:09:43,140
‫to simply call this function here the error controller,

194
00:09:43,140 --> 00:09:46,500
‫and here I wanted to paste that middleware function,

195
00:09:46,500 --> 00:09:49,173
‫but I guess I didn't copy it, so let's do that again.

196
00:09:51,010 --> 00:09:53,540
‫All right, and so actually I'm gonna export

197
00:09:53,540 --> 00:09:56,240
‫this one here as the module.exports

198
00:09:56,240 --> 00:09:57,676
‫because the other handle functions

199
00:09:57,676 --> 00:09:59,606
‫that we're gonna create later on,

200
00:09:59,606 --> 00:10:02,440
‫I will not export them from here.

201
00:10:02,440 --> 00:10:05,453
‫So they are just kinda just gonna be helpers.

202
00:10:06,320 --> 00:10:11,320
‫So, module.exports equals this function, okay?

203
00:10:12,210 --> 00:10:15,420
‫Let's actually get rid of this console.log here,

204
00:10:15,420 --> 00:10:18,510
‫give it a save, and now back into our app

205
00:10:18,510 --> 00:10:21,080
‫we of course now need to plug in

206
00:10:21,080 --> 00:10:23,040
‫that middleware function here.

207
00:10:23,040 --> 00:10:25,660
‫So, let's again go ahead and import it

208
00:10:26,700 --> 00:10:28,710
‫and I can call it whatever I want,

209
00:10:28,710 --> 00:10:29,760
‫and so let me call it

210
00:10:30,802 --> 00:10:32,635
‫the globalErrorHandler

211
00:10:34,679 --> 00:10:36,853
‫with a capital H,

212
00:10:38,650 --> 00:10:39,840
‫and I'm gonna require

213
00:10:42,300 --> 00:10:45,033
‫controllers and errorController.

214
00:10:49,700 --> 00:10:52,660
‫Put it back here, and now for the final test

215
00:10:52,660 --> 00:10:54,343
‫after this refactoring.

216
00:10:55,810 --> 00:10:58,970
‫Let's see, and indeed

217
00:10:58,970 --> 00:11:03,040
‫one more time, everything works just fine, okay?

218
00:11:03,040 --> 00:11:06,490
‫So, perfect, that was the goal for this video,

219
00:11:06,490 --> 00:11:07,690
‫see you in the next one.

