From the course: Building a Website with Node.js and Express.js

How to handle errors in express

From the course: Building a Website with Node.js and Express.js

Start my 1-month free trial

How to handle errors in express

- [Instructor] Mistakes happen. Be it some syntax problem or a field database call. Your application will run into errors and if they aren't handled gracefully, the question isn't if but when some error will take down your website and you get an angry call from a client. There're a few patterns and good practices to gracefully deal with errors in Express. We're already learned that in Express, each middleware function can either send a response which ends the request cycle or call the next middleware in the chain using next. But what happens when an error occurs inside the middleware or route? Let's try this out. So I open server.js and in there, I will just create some route that simulates an error. I do this right after the express.static middleware. I add app.get /throw and this gets as we know a request, response and the next argument and in there, I will now use the regular JavaScript function, throw new Error and I say Something did throw. Let's open the browser to run this route, so it's /throw localhost:3000/throw and we see we get the error message and we also get the so-called stack trace. It's not pretty but the application is still running so when I head back to the index page, I see that everything is still generally fine. In my console, I also see that the error was logged out here. So that's the default provided by Express. So using throw would be a legit way to report an arrow. When something goes wrong, just throw an error and Express will show some error message. This is true as long as you aren't in an asynchronous invocation. I show you that by simply using setTimeout. That's an easy way to simulate asynchronicity in Node.js, so I will create the setTimeout function here. And I move this throw statement into setTimeout and this should run after say 500 milliseconds. Let's open this throw root again and we see that now we get a pretty solid error. So this site cannot be reached and when I look back on the website on the index page, I see that the page is down. Looking into Visual Studio Code again, I see that Nodemon tells us that the app crashed. So as we see, throwing from an asynchronous invocation will crash your app and this is obviously something you want to and have to avoid. So how can we return errors from asynchronous invocations? This is where next comes into play again because next accepts an error as first argument. So if I now run into an error in this timeout function, I can simply do a return next and I don't use throw anymore but I just return the error object here. And when I head back to my /throw route, I see that we get now a proper error back. The stack trace is shorter because it's in an asynchronous invocation and there Node.js does not see so much of what happened before. So as we learned now, our general rule is to never throw from your Express routes and middlewares because it can take down your whole application. Nowadays, we also have async await and we use a lot throughout this course. With async await, we don't have a callback as we have it here in setTimeout and we need another way to handle errors that happen in this asynchronous invocation. So to try that out, we can just use the middleware that we created before to get the names and I remove this row route again and I will just now go into this getNames function and I will throw from there. So in this map function, maybe that returns us the speakers, I will now throw an error, throw new Error. And I call it Async await error. Next, let's reload the index page and we see that the application hangs completely. So this is bad again. Application not reachable. Completely broken. So what happened here? When I look into the error message on the console, I see that I get an unhandled promise rejection warning. This means that we got an error but it was not properly handled. So how can we handle that? In server.js, I will now use a try catch block, so add try, catch, you should be familiar with that. So that's regular JavaScript and all the code goes into the try block but if something goes wrong, I end up in the catch block and there I get an error object where I can now simply do a return next error again. Let's reload the page and we see that we get now this Async await error. It's still not pretty but it does not take down our application. Next, let's apply what we just learned to the routes we already created so I go to the index route and there I will now create a new try catch statement and I copy over all this old code block into the try block and if an error occurs, I return next error and I have to get next as function argument here because I only had request, response because I was not using next yet. This looks good but now ESLint complains we now also have to return from the try block. I do the same now for the speakers route. Again, a try catch block. And there I move the code over here. And do a return next error. And now you should know already how this works. I'm doing that also for the speakers-detail. So while we're doing that, we have the good feeling of making our app really resilient to any error that could occur. And a return from here as well and all that and I also have to get this next callback as argument and finally, let's do this also for feedback. So always when you see an await statement in a route, it's a good call to use try catch to handle a possible error within this asynchronous invocation. So now application is way more resilient to errors than it was before but we also saw that this default error page by Express is not really pretty or user friendly. So if a user runs into that, they will most probably think something is terribly wrong with the website. We should find a way to override the Express default error handler and show something more pretty to the user in case something happens and we will do that right now.

Contents