I have the following express controller
class ThingsController {
static async index(req, res, next) {
try {
const things = await Thing.all();
res.json(things);
} catch(err) {
next(err);
}
}
}
and router
router.route('/things').get(ThingsController.index)
In my app I plan to have several controllers which use promises to render the result
I do not want to repeat try/catch block every time
My first solution was to extract this logic into handle promise rejection function:
const handlePromiseRejection = (handler) =>
async (req, res, next) => {
try{
await handler(req, res, next);
} catch(err) {
next(err);
};
};
and now we can remove try/catch block from the ThingsController.index and need to change router to this:
router.route('/things')
.get(handlePromiseRejection(ThingsController.index))
But adding handlePromiseRejection
on every route might be tedious task and I would want to have more clever solution.
Do you have any ideas?
Normal way of handling errors with async/await
in routes is to catch the errors and pass it to the catch all
error handler:
app.use(async (req, res) => {
try {
const user = await someAction();
} catch (err) {
// pass to error handler
next(err)
}
});
app.use((err, req, res, next) => {
// handle error here
console.error(err);
});
With express-async-errors
package, you could simply throw
(or not worry about error
thrown from some function). From docs: Instead of patching all methods on an express Router, it wraps the Layer#handle property in one place, leaving all the rest of the express guts intact.
Usage is simple:
require('express-async-errors'); // just require!
app.use(async (req, res) => {
const user = await User.findByToken(req.get('authorization')); // could possibly throw error, implicitly does catch and next(err) for you
// throw some error and let it be implicitly handled !!
if (!user) throw Error("access denied");
});
app.use((err, req, res, next) => {
// handle error
console.error(err);
});