‫In this lecture, let's implement a better way
‫of catching errors in all our async functions.
‫So right now, in all our async functions,
‫we have these try catch blocks, right?
‫So, remember how we added to all of these handle functions
‫this try and then this catch block, okay?
‫And so all of them have this
‫because all of them are async functions
‫and that's how we usually catch the errors
‫inside of an asynchronous function.
‫So using a try catch block.
‫Now that really makes our code look messy and unfocused
‫so the goal of this createTour method here, for example,
‫is to just run this code.
‫We actually do not want to mess around
‫with error handling here,
‫so right now we have these two extra blocks,
‫try and catch, and with that comes
‫this extra indentation here
‫and so again, this really makes our code look not clean.
‫It's really not focused.
‫Also, we have a lot of duplicate code here
‫because in each of these handlers,
‫we have quite a similar catch block.
‫So in all of this, all we're doing is
‫really to send this response.
‫And that response would actually not even be sent here
‫but instead in our global error handling middleware,
‫remember, but that's another topic.
‫For now, what I'm trying to focus here
‫is that these try catch blocks inside
‫of each of our async functions are not ideal
‫and so let's now try to fix that.
‫And the solution is to basically take the try catch block
‫out of here and put it on a higher level
‫in another function.
‫So basically what we're gonna do
‫is to create a function,
‫and then wrap this async function into that function.
‫All right?
‫And so let me call that one catchAsync.
‫So catchAsync, and I'm calling it this way
‫because the goal of this function
‫is to simply catch our asynchronous errors.
‫So simple, right?
‫So into this catchAsync function,
‫we will pass in a function, okay?
‫And remember, the function that we're gonna pass in
‫is basically this one.
‫So now that we're working with this example
‫the function that we will pass into the catchAsync
‫is this function because this is where we want
‫to catch the asynchronous errors.
‫So let's actually do that.
‫So fn, and then wrap that entire function into there.
‫So next up, what we then have to do
‫is to actually call this function in here.
‫So call it, and this function should receive
‫request, response, and in fact, also next.
‫So this one here should actually also have next
‫and all the others, as well,
‫because remember, we need the next function
‫in order to pass the error into it
‫so that that error can then be handled
‫in the global error handling middleware.
‫So all of these functions are gonna need
‫request, response, and next.
‫But let's leave that for later.
‫For now, let's really focus on our catchAsync here.
‫So this function here that we passed into async,
‫which is now called fn up here,
‫is an asynchronous function.
‫And remember that asynchronous functions
‫return promises, right?
‫And when there is an error inside of an async function,
‫that basically means that the promise gets rejected.
‫And so up here, where we actually call that function,
‫we can then catch that error.
‫So we catch it here, instead of catching it
‫in the try catch block.
‫So catch, and error, and then next, and pass the error.
‫And we can simplify this,
‫but for now let's remove the try catch block here,
‫and so simply focus on this piece.
‫So this is all we want
‫and we no longer need the try catch block,
‫again, because that catch is now basically transferred
‫to here, to this line.
‫It's no longer a catch block,
‫because in here it's just easier to use
‫the promise that the fn function returns.
‫So again, this fn function is this function,
‫so the one that we passed into catchAsync,
‫and so that is gonna return a promise.
‫And actually, I noticed here that this, of course,
‫should be called catchAsync, all right?
‫And then so that function that we passed
‫into catchAsync, this one is of course then fn.
‫All right?
‫So the argument that we passed in there.
‫Now there are actually two big problems
‫with the way that this is implemented right now
‫and so this way, it wouldn't really work at all.
‫So first one, this function call here
‫has no way of knowing request, response, and next.
‫We did not pass them into catchAsync here,
‫and so really there's no way
‫for the function to know the values of these parameters.
‫And second is that right here
‫we are actually calling the async function.
‫And to see this a bit better, let's just
‫get completely rid of this code.
‫So here we have catchAsync and we are then calling it
‫using the parentheses of course.
‫And then inside of catchAsync we are also then
‫right away calling the fn function,
‫and that's not how it is supposed to work.
‫So createTour here should really be a function
‫but not the result of calling a function.
‫But that's right now what's happening.
‫So right now catchAsync is being called,
‫which then calls this function here, okay?
‫And so again, this function should not called,
‫but instead it should sit here and wait
‫until express calls it.
‫And express will of course call it
‫as soon as someone hits the route
‫that needs this control function.
‫And so the solution to that is to basically make
‫the catchAsync function return another function
‫which is then gonna be assigned to createTour
‫and so that function can then
‫later be called when necessary.
‫So let's do that here.
‫So let's return an anonymous function
‫and so remember that this is the function
‫that express is then gonna call.
‫And so here is where we then specify
‫request, response, and next.
‫Actually missing the arrow here.
‫And all right.
‫And that's actually it.
‫That's our catchAsync function.
‫Just remember how I said that we could simplify it
‫and that's just because, in JavaScript,
‫we can simplify it like this
‫so all we need to pass here is the function,
‫and it will then be called automatically
‫with the parameter that this callback receives.
‫So it's the same as writing next.
‫So let's recap here.
‫So in order to get rid our try catch blocks,
‫we simply wrapped our asynchronous function
‫inside of the catchAsync function that we just created.
‫This function will then return a new anonymous function,
‫which is this one here,
‫which will then be assigned to createTour.
‫And so basically it is this function here
‫that will get called as soon as a new tour
‫should be created using the createTour handler.
‫And so that's why it has the exact same signature here
‫as this async function, with request, response, and next.
‫Now what this function here will then do
‫is that it will call the function
‫that we passed in initially,
‫so this one here,
‫and it will then execute all the code that is in there.
‫Now since it's an async function here,
‫it will return a promise
‫and therefore, in case there is an error in this promise
‫or in other words, in case it gets rejected,
‫we can then catch the error that happened
‫using the catch method that is available on all promises.
‫And in the end, it is this catch method here
‫which will pass the error into the next function
‫which will then make it so that our error
‫ends up in our global error handling middleware.
‫So this here, this line of code,
‫is really where all the magic happens,
‫and this is, in fact, what allows us
‫to get rid of the catch block that we had previously.
‫And a note:
‫this is quite complicated to wrap your head around
‫and in case that it's not 100% clear,
‫don't worry, it's not all that important.
‫This is really just about figuring out how exactly
‫asynchronous code works behind the scenes in JavaScript.
‫So it's not really so much about express or Node.js,
‫this is more about how asynchronous code works.
‫Now anyway, if we now create a new tour
‫and some error happens,
‫for example, from an invalid input,
‫then that error should of course be catched here
‫in this catch function,
‫and will then be propagated to our error handling middleware
‫and so that one will then send back the error response
‫that we're expected to receive.
‫And so let's now actually try that out.
‫So create a new tour.
‫Here we have the body,
‫and let's now get rid of one of these required fields.
‫All right.
‫And so that should trigger an error, and so let's see.
‫And indeed, our tour validation failed,
‫which is exactly the error message
‫that we were supposed to receive.
‫Now here, you see this 500 Internal Server Error,
‫which is simply due to the fact that right now
‫the error that was propagated
‫to the error handling middleware
‫did not have any status code specified
‫and so remember our default is 500
‫and so that's the one that was then sent back.
‫And of course, we need to fix that
‫and we will do that in a later lecture in this course.
‫For now, what matters here is that first,
‫our catchAsync function works just as intended,
‫and second, that the error was actually propagated,
‫so it was catched by our global error handling middleware
‫which then sent this response back to the client.
‫Now let's actually go ahead and export
‫this catch function into its own file.
‫So I'm grabbing it from here
‫and I will create just another file
‫into our utilities folder.
‫So catchAsync.js.
‫And to here, module.exports should be just this.
‫And so that should work just fine.
‫Back in our tour controller we of course
‫now need to import this function.
‫And as usual, we need to go up one folder
‫and then into our utilities folder
‫and then catchAsync.
‫All right, and now all we need to do
‫is to get rid of all these catch blocks
‫and wrap all the handlers into the catchAsync.
‫So let's do that.
‫First do the wrapping, and then getting rid of these blocks.
‫Give it a save to reformat, and here we go.
‫And now it's simply a process of repeating this
‫until all of the tours, or,
‫sorry, until all of the handlers are done.
‫Okay, quick save.
‫This one is already done.
‫Next up is update.
‫And only one more missing.
‫Or actually, that's not true.
‫Down there we have even more async functions.
‫So we'll get rid of the catch and the try here.
‫And I believe this one is the last one.
‫And yeah, indeed it is.
‫All right, now one other thing that we need to do
‫is actually add next to all of them here as well.
‫But of course, not in uppercase.
‫Okay.
‫And let me actually just select all of them here
‫so that I only have to write it once.
‫And so that added it to all of them.
‫And so now I guess we're done with this part.
‫Let's just very quickly test it again,
‫not with this one, but here with,
‫not with this one as well, so we're done.
‫And I'm gonna try to get a tour
‫but with an invalid ID, so let's see what happens here.
‫And indeed, we get our error message
‫and again with the 500 status code,
‫which is not correct, remember,
‫but we're gonna take care of that
‫at a later point in time.
‫So right now, let me show you
‫that this here is where the 500 comes from
‫because right now there's no status code
‫inside of the error that we get
‫because these errors, they actually come from Mongoose
‫and so we have no way of adding
‫a status code to these errors.
‫Or actually, of course, we could do it,
‫but that would just be even more confusing
‫and so we're gonna find another way
‫later in this section.
‫For now, I'm really happy with the result that we have here
‫and so that's it for this lecture.