Hi everyone, hope you all are doing ok in the COVID-19 world.
Recently I've been playing around with Express, and I needed to setup an error handler for my project.
I have been searching for a way to catch all exceptions in my project, something that will work both for sync and async routes.
To my surprise, I couldn't find an easy solution for it, so I had to come up with something of my own.
Let's walk it through:
first define your error handler
errorHandler.js:
const handleErrors = (err, req, res, next) => {
if (res.headersSent) return next(err);
// more handle error logic should be inserted here.
res.status(500).json({
msg: "Server Error",
});
module.exports = handleErrors;
register your error handler (after all your routes)
server.js:
// Middlewares
app.use(cors());
app.use(express.json());
app.use(fileupload());
app.use(cookies());
// Routes
app.use("/", routes);
app.use(handleErrors); <------
Now we are going to do some javascript magic, we are going to leverage "express-async-handler" and write some of our own magic, to make the global exception handler work.
now we are going to hook express.Router which will return a new router that will have error handling for both async/sync routes
hookRouter.js
const express = require("express");
const originalRouterFunc = express.Router;
const asyncHandler = require("express-async-handler");
export function hookRouter() {
function hookAllRouteMethods(router) {
const methods = ["get", "post", "put", "delete", "options", "head", "all", "use"]; // all router methods
methods.forEach(method => {
const originalRouterFunc = router[method];
const hookedRouterMethod = async function (path, ...routeHandlers) {
routeHandlers = routeHandlers.map(f =>
asyncHandler(function (req, res, next) { // async error handler
// sync error handler start
try {
return f(req, res, next); // original route handler
} catch (e) {
console.log("hahah I caught you =)");
next(e, req, res); // pass exception to our error handler.
}
// sync error handler end
})
);
originalRouterFunc.apply(router, [path, ...routeHandlers]);
};
router[method] = hookedRouterMethod;
});
}
function hookRouterCreation() {
express.Router = function () {
const router = originalRouterFunc.apply(this, arguments);
hookAllRouteMethods(router);
return router;
};
}
hookRouterCreation();
}
next, we just have to hook our router at the top of server.js (or before you use routes):
const { hookRouter } = require("./hookRouter");
hookRouter();
That's it! now everytime you will use express.Router() it will have your error handler !
Hope this was helpful for you, Also this solution is still not 'battle tested' so I would like to hear what you guys think =).
Top comments (0)