1 00:00:01,050 --> 00:00:02,840 Let's now make some more use 2 00:00:02,840 --> 00:00:04,780 of our AppError class 3 00:00:04,780 --> 00:00:07,400 business adding a couple of 404 errors 4 00:00:07,400 --> 00:00:09,493 and some of our tour handler functions. 5 00:00:10,446 --> 00:00:12,740 Now just one thing that I wanted to say 6 00:00:12,740 --> 00:00:16,030 before we actually implement these 404 errors 7 00:00:16,030 --> 00:00:19,640 is that of course we could have used the catchAsync function 8 00:00:19,640 --> 00:00:22,290 also in our router, okay? 9 00:00:22,290 --> 00:00:24,940 So, let me show you how that would work. 10 00:00:24,940 --> 00:00:27,090 So, here in TourRoutes, 11 00:00:27,090 --> 00:00:29,730 I could have wrapped this function here 12 00:00:30,750 --> 00:00:34,530 into catchAsync just like this 13 00:00:34,530 --> 00:00:38,480 instead of doing it right in here in the controller. 14 00:00:38,480 --> 00:00:41,400 So, here where I did it in fact, right? 15 00:00:41,400 --> 00:00:44,200 And that would have had the exact same result 16 00:00:44,200 --> 00:00:45,950 but I didn't do it this way 17 00:00:45,950 --> 00:00:48,190 because like this, I have to remember 18 00:00:48,190 --> 00:00:50,110 which of these methods here 19 00:00:50,110 --> 00:00:52,350 is actually an sync method, 20 00:00:52,350 --> 00:00:54,800 okay, so that only on those 21 00:00:54,800 --> 00:00:58,960 I actually add the catchAsync function, right? 22 00:00:58,960 --> 00:01:02,150 Now in this case, actually all of them are async function 23 00:01:02,150 --> 00:01:05,700 and so, that's not really the matter here in this example 24 00:01:05,700 --> 00:01:07,530 but there will be some examples later 25 00:01:07,530 --> 00:01:11,150 where not all the handlers are asynchronous functions 26 00:01:11,150 --> 00:01:12,170 and so, in that case, 27 00:01:12,170 --> 00:01:14,020 I would really have to remember 28 00:01:14,020 --> 00:01:17,100 which of them I have to wrap into catchAsync 29 00:01:17,100 --> 00:01:18,600 and which ones not 30 00:01:18,600 --> 00:01:20,450 and so, in doing it in the controller 31 00:01:20,450 --> 00:01:23,930 is much easier because simply each time that I'm writing 32 00:01:23,930 --> 00:01:25,520 an async function here, 33 00:01:25,520 --> 00:01:27,190 they already know well, 34 00:01:27,190 --> 00:01:30,220 I need to wrap it into catchAsync. 35 00:01:30,220 --> 00:01:31,350 Okay. 36 00:01:31,350 --> 00:01:32,880 So, I'm not doing it here, 37 00:01:32,880 --> 00:01:36,400 I just do it like I showed you in the last video. 38 00:01:36,400 --> 00:01:39,680 Okay and actually I once run into a bug 39 00:01:39,680 --> 00:01:41,330 that was really hard to find 40 00:01:41,330 --> 00:01:43,160 because I actually wrapped a function 41 00:01:43,160 --> 00:01:45,690 that was not async into catchAsync 42 00:01:45,690 --> 00:01:47,850 and so that we really not working 43 00:01:47,850 --> 00:01:50,350 and I couldn't figure out where the bug was 44 00:01:50,350 --> 00:01:52,830 and wasted a lot of time on that one. 45 00:01:52,830 --> 00:01:56,820 And so, since then, I no longer put catchAsync here 46 00:01:56,820 --> 00:01:59,610 but really close to where I actually need it, 47 00:01:59,610 --> 00:02:02,860 so close to the code that is actually asynchronous. 48 00:02:02,860 --> 00:02:04,640 Okay and with that being said, 49 00:02:04,640 --> 00:02:07,820 let's now implement some 404 errors here. 50 00:02:07,820 --> 00:02:09,680 All right, so I wanna start 51 00:02:09,680 --> 00:02:11,680 by showing you again the example 52 00:02:11,680 --> 00:02:13,830 that we did in the last video. 53 00:02:13,830 --> 00:02:16,350 Okay, so we tried to get a tour 54 00:02:16,350 --> 00:02:19,780 for this weird ID that does not really exist 55 00:02:19,780 --> 00:02:20,989 and the error that we got 56 00:02:20,989 --> 00:02:23,690 is that basically Mongoose 57 00:02:23,690 --> 00:02:26,410 could not convert this string here 58 00:02:26,410 --> 00:02:29,630 into a valid ID for MongoDB. 59 00:02:29,630 --> 00:02:33,653 But what happens when we actually use a valid MongoDB ID? 60 00:02:34,750 --> 00:02:38,003 So, for example, let's, yeah, 61 00:02:38,003 --> 00:02:39,173 let's copy this one here, 62 00:02:41,660 --> 00:02:44,670 okay, and this one of course will have a result 63 00:02:44,670 --> 00:02:47,770 and so, let's just slightly change it, 64 00:02:47,770 --> 00:02:50,060 so for example, changing this to zero here 65 00:02:50,060 --> 00:02:52,340 will still be a valid ID, 66 00:02:52,340 --> 00:02:53,900 so it looks like this 67 00:02:53,900 --> 00:02:56,000 and it looks exactly the same as before, 68 00:02:56,000 --> 00:02:57,440 I just changed one number 69 00:02:57,440 --> 00:03:00,830 but this ID will probably not exist. 70 00:03:00,830 --> 00:03:03,470 And so, let's see what we get then. 71 00:03:03,470 --> 00:03:06,810 And indeed, now our result here is null. 72 00:03:06,810 --> 00:03:10,340 All right, and so, that's not really what we want, is it? 73 00:03:10,340 --> 00:03:14,550 What we want here is to show a 404 status code in here 74 00:03:14,550 --> 00:03:17,310 and say that this tour was not found. 75 00:03:17,310 --> 00:03:20,750 Okay and so, let's now use orAppError class 76 00:03:20,750 --> 00:03:22,580 in order to implement that. 77 00:03:22,580 --> 00:03:24,040 Just keep in mind that the tour 78 00:03:24,040 --> 00:03:26,880 that we get back here is null, okay? 79 00:03:26,880 --> 00:03:29,453 So, null that we can now test for. 80 00:03:30,920 --> 00:03:33,533 So, if we go to our getTour handler, 81 00:03:35,260 --> 00:03:40,260 let's now implement if there is no tour 82 00:03:41,030 --> 00:03:43,390 and in that case we will create or error 83 00:03:44,410 --> 00:03:45,243 and this here works 84 00:03:45,243 --> 00:03:46,650 because if there's no tour, 85 00:03:46,650 --> 00:03:47,710 it will be null. 86 00:03:47,710 --> 00:03:51,610 Remember and in JavaScript, null is a fallacy value, 87 00:03:51,610 --> 00:03:54,660 so a value that will convert to false here 88 00:03:54,660 --> 00:03:56,250 in an if statement. 89 00:03:56,250 --> 00:03:58,060 Okay, and so, if there's no tour, 90 00:03:58,060 --> 00:03:59,450 then tour is false 91 00:03:59,450 --> 00:04:01,790 and then not false is of course true 92 00:04:01,790 --> 00:04:04,830 and so, that's then how we enter this if block. 93 00:04:04,830 --> 00:04:07,600 So, what do we want to do if there is no tour? 94 00:04:07,600 --> 00:04:11,530 Well, we want to create next with an error. 95 00:04:11,530 --> 00:04:14,861 So, in order to jump straight into or error 96 00:04:14,861 --> 00:04:15,990 and linked middleware. 97 00:04:15,990 --> 00:04:18,870 So, we do new AppError 98 00:04:20,610 --> 00:04:23,350 which si not available yet, we still have to import it 99 00:04:23,350 --> 00:04:26,120 but let's use it here right away. 100 00:04:26,120 --> 00:04:27,950 Okay, and then let's just say 101 00:04:30,500 --> 00:04:34,673 No tour found with that ID. 102 00:04:35,580 --> 00:04:37,070 And then a status code remember 103 00:04:37,070 --> 00:04:40,940 is the second argument is 404, all right? 104 00:04:40,940 --> 00:04:43,460 Now one last thing that we need to do here 105 00:04:43,460 --> 00:04:46,470 which is to say return, okay 106 00:04:46,470 --> 00:04:49,410 because we want to return this function immediately 107 00:04:49,410 --> 00:04:52,250 and not move on to the next line 108 00:04:52,250 --> 00:04:53,690 which would be this one 109 00:04:53,690 --> 00:04:57,800 and which would then basically try to send two responses 110 00:04:57,800 --> 00:05:00,210 and we did already run into that error before, 111 00:05:00,210 --> 00:05:02,020 so I'll hope you'll remember that 112 00:05:02,020 --> 00:05:05,580 and that's the reason why we always need return here. 113 00:05:05,580 --> 00:05:09,610 Okay, let's now go ahead and quickly import the appError 114 00:05:10,870 --> 00:05:13,200 and that's similar to this one here, 115 00:05:13,200 --> 00:05:14,823 so let's just duplicate. 116 00:05:17,990 --> 00:05:21,203 Okay, and here it's actually with a capital A. 117 00:05:22,170 --> 00:05:24,210 All right, give it a save 118 00:05:24,210 --> 00:05:25,850 and let's now try it again 119 00:05:27,160 --> 00:05:31,450 and now indeed no tour found with that ID 404. 120 00:05:31,450 --> 00:05:34,440 Perfect, so exactly what we wanted. 121 00:05:34,440 --> 00:05:37,170 Oh and you also saw that we have the failed here. 122 00:05:37,170 --> 00:05:40,980 Okay and so that comes from or class as well. 123 00:05:40,980 --> 00:05:44,270 Great, so that works and so I really hope 124 00:05:44,270 --> 00:05:48,060 that by now you understood exactly how all 125 00:05:48,060 --> 00:05:50,370 of this error handling now works. 126 00:05:50,370 --> 00:05:53,300 Okay, so again we create an error 127 00:05:53,300 --> 00:05:55,450 and we then pass that error into next 128 00:05:55,450 --> 00:05:57,820 and as soon as next receives something, 129 00:05:57,820 --> 00:05:59,880 it assumes that it is an error 130 00:05:59,880 --> 00:06:00,757 and it will jump straight 131 00:06:00,757 --> 00:06:03,630 into the global error handling middleware 132 00:06:03,630 --> 00:06:06,683 which will then send the response for us, okay? 133 00:06:08,210 --> 00:06:09,850 So, let's copy this one 134 00:06:09,850 --> 00:06:12,410 and put it in all the other handlers 135 00:06:12,410 --> 00:06:15,600 that query documents based on the ID. 136 00:06:15,600 --> 00:06:20,470 So, not create tour but update a tour, okay? 137 00:06:20,470 --> 00:06:21,380 And so, here the same, 138 00:06:21,380 --> 00:06:23,120 if we're trying to update the tour 139 00:06:23,120 --> 00:06:24,360 that does not exist, 140 00:06:24,360 --> 00:06:26,773 it will then give us the exact same error. 141 00:06:29,210 --> 00:06:32,470 Finally of course the same with delete. 142 00:06:32,470 --> 00:06:35,870 And now you see that ESLint gave me this error here 143 00:06:35,870 --> 00:06:38,710 and so, that's because this tour is not defined 144 00:06:38,710 --> 00:06:41,730 and in this case, ESLint really saved me here 145 00:06:41,730 --> 00:06:43,660 from creating this bug. 146 00:06:43,660 --> 00:06:44,550 Right? 147 00:06:44,550 --> 00:06:46,790 So, again without ESLint, 148 00:06:46,790 --> 00:06:48,570 I would have probably just pasted it here 149 00:06:48,570 --> 00:06:49,920 and called it a day 150 00:06:49,920 --> 00:06:53,050 without even noticing that tour is nowhere defined 151 00:06:53,050 --> 00:06:54,600 inside of this function 152 00:06:54,600 --> 00:06:57,830 but since we installed this really valuable tool, 153 00:06:57,830 --> 00:06:59,970 I can now go ahead and fix it. 154 00:06:59,970 --> 00:07:01,820 All right, so up until this point, 155 00:07:01,820 --> 00:07:06,490 we simply awaited this delete instruction here 156 00:07:06,490 --> 00:07:08,460 and didn't save the result of it 157 00:07:08,460 --> 00:07:10,710 and that's simply because we didn't need it. 158 00:07:10,710 --> 00:07:13,200 Okay, but right now we actually do need it 159 00:07:13,200 --> 00:07:15,140 because we want this tour variable 160 00:07:15,140 --> 00:07:18,413 in order to verify if there actually is a tour or not. 161 00:07:21,460 --> 00:07:23,760 So, very easy, const tour 162 00:07:23,760 --> 00:07:25,350 and then equal to that result, 163 00:07:25,350 --> 00:07:27,450 give it a save and then the error is gone. 164 00:07:28,610 --> 00:07:29,820 So, great. 165 00:07:29,820 --> 00:07:32,770 ESLint at work, all right? 166 00:07:32,770 --> 00:07:37,770 Now maybe you noticed that I did not add this 404 error here 167 00:07:37,950 --> 00:07:40,000 in this getAllTour handler. 168 00:07:40,000 --> 00:07:41,910 So, why did I did that? 169 00:07:41,910 --> 00:07:43,620 And so let me explain you why. 170 00:07:43,620 --> 00:07:46,330 So, when there is zero results found, 171 00:07:46,330 --> 00:07:50,530 for example, there are no results matching for a filter, 172 00:07:50,530 --> 00:07:52,520 or because the page was requested 173 00:07:52,520 --> 00:07:55,970 that doesn't exist, then of course we could consider sending 174 00:07:55,970 --> 00:07:58,550 a 404 error and saying that the data 175 00:07:58,550 --> 00:08:01,220 was not found but in my opinion 176 00:08:01,220 --> 00:08:03,760 and also the opinion of other developers, 177 00:08:03,760 --> 00:08:07,170 that is not entirely correct in this request 178 00:08:07,170 --> 00:08:09,240 because there was not really an error. 179 00:08:09,240 --> 00:08:11,950 I mean, the request was correctly received. 180 00:08:11,950 --> 00:08:14,550 The database correctly searched for the tours 181 00:08:14,550 --> 00:08:16,950 and found exactly zero records 182 00:08:16,950 --> 00:08:19,150 and so, these zero records are exactly 183 00:08:19,150 --> 00:08:23,250 what we're gonna send back along with the 200 HTTP code. 184 00:08:23,250 --> 00:08:25,120 All right, so again I consider 185 00:08:25,120 --> 00:08:27,300 that there cannot really be an error 186 00:08:27,300 --> 00:08:29,610 when a user requests all the tours 187 00:08:29,610 --> 00:08:32,680 unless of course there is some failure in the database 188 00:08:32,680 --> 00:08:33,850 or something like that. 189 00:08:33,850 --> 00:08:35,210 But in that case, Mongoose 190 00:08:35,210 --> 00:08:37,600 will then automatically throw an error. 191 00:08:37,600 --> 00:08:40,950 Right, which then in turn is gonna get catched 192 00:08:40,950 --> 00:08:42,920 by our or catchAsync function 193 00:08:42,920 --> 00:08:44,330 and as you already know, 194 00:08:44,330 --> 00:08:47,510 handled in our global error handler 195 00:08:47,510 --> 00:08:48,800 and as you already know, 196 00:08:48,800 --> 00:08:52,000 handled in our global error handling middleware. 197 00:08:52,000 --> 00:08:55,640 All right, so I've said these words so many times by now. 198 00:08:55,640 --> 00:08:57,717 Anyway, I hope that made sense 199 00:08:57,717 --> 00:09:01,113 and so, yeah, let's now move on.