Keep your routes error handlers simple and flexible for your nodejs/express app
Wow.. My first story. Well, let’s try)
Each of us thought how to make good error handling with logging, scalability and allow this system to be flexible. I gonna to share with you my thoughts how to do this and would like to talk what structure you might to stick in your nodejs apps.
So, here we go.
First of all let’s make pretty simple nodejs/express server with couple routes.
Good. Now let’s add couple controllers. One of them will just produce some response data, but another one will raise error.
If we run server and go to `localhost:3000/two` it fails like this
It can be easily intercept by adding one middleware
app.use((err, req, res, next) => {
res.json({ message: err.message });
});
Now we handle errors through all routes, but missed one thing: each error may have own status code.
Let’s add new route with :id
param in path
app.get("/:id", (req, res) => {
const data = userCtrl(req.params.id);
res.json({ message: data.name });
});
userCtrl
we will consider a bit later.
Now we are close to one of the ways to solve our main problem. Create file exceptions.js
and put there this content
General idea is implementing custom error class based on Error and extend it with all necessary fields. You can add custom logging there as well.
Add new controller and emulate DB (just create simple object what will map ids with names). Now controllers.js
looks like this
Here is time to play with all of it. Go to new route with id 1
And check this route for id 12
as well
Great. Now we can see error message what we expect. But status still 200. We need to update error middleware a bit:
app.use((err, req, res, next) => {
const { statusCode = 500 } = err;
res.status(statusCode).json({ message: err.message });
});
Here we check status code from err
variable and if this is missing — set default status code 500
.
For our case we will receive 404 error. Cool!
Such error rising we can implement via another way: instead of passing Error object as throw
param you can pass there simple object like this
throw { message: "Value param is broken", statusCode: 404 };
Handling of this error will be the same with previous way.
First way has two advantages:
1) full customizable
2) you can get trace of the error via processing err.stack
field and get broken place of you code
Second way is pretty simple and doesn’t take a lot of code.
Thanks for the reading. Link to github you can find below. Bye!