Loading lessons...
Async Error Wrapping (express-async-handler)
Handling Unhandled Rejections in Async Routes
Synchronous errors inside route handlers are automatically caught by Express. However, unhandled promise rejections inside async route functions will hang the request unless explicitly caught or wrapped!
Manual try/catch Approach
app.get("/users/:id", async (req, res, next) => {
try {
const user = await User.findById(req.params.id);
if (!user) throw new Error("User not found");
res.json(user);
} catch (err) {
next(err); // Must call next(err) manually!
}
});
Cleaner Solution: Higher-Order Async Wrapper
Avoid repeating try/catch in dozens of routes by wrapping async route handlers:
// Higher-order function wrapper
const asyncHandler = (fn) => (req, res, next) => {
Promise.resolve(fn(req, res, next)).catch(next);
};
// Usage with asyncHandler (No try/catch block needed!)
app.get("/users/:id", asyncHandler(async (req, res) => {
const user = await User.findById(req.params.id);
if (!user) {
const error = new Error("User not found");
error.statusCode = 404;
throw error;
}
res.json(user);
}));
TL;DR
- Async routes throw unhandled rejections if errors are not caught.
- Use an
asyncHandlerutility or theexpress-async-errorspackage to eliminate repetitivetry/catchblocks.