Async Handler
The Async Handler component is a foundational Express utility that ensures all errors thrown inside asynchronous route handlers are reliably captured and forwarded to Express’s global error middleware.
It eliminates repetitive try/catch blocks and ensures all rejected promises are properly forwarded to Express’s centralized error-handling middleware.
- Eliminates try/catch boilerplate,
- Full TypeScript support,
- Seamless Express integration,
- Minimal performance overhead,
- Works with any error handler
This component is designed to be:
- Minimal
- Framework-native
- Fully type-safe
- Compatible with any Express error handler
Installation Guide
Install the component using the ServerCN CLI:
npx servercn add async-handlerThe Core Problem in Express
Express was originally designed around synchronous middleware. Express.js doesn't automatically catch errors from async functions
Async Handler wraps async routes and properly forwards all errors.
As a result:
- Errors thrown synchronously are caught automatically
- Errors thrown inside async functions are not
router.get("/users", async (_req, res) => {
throw new Error("Database unavailable");
});Basic Implementation
1. MVC Structure
src/utils/async-handler.ts
import { Request, Response, NextFunction } from "express";
export type AsyncRouteHandler = (
req: Request,
res: Response,
next: NextFunction
) => Promise<unknown>;
export function AsyncHandler(fn: AsyncRouteHandler) {
return function (req: Request, res: Response, next: NextFunction) {
Promise.resolve(fn(req, res, next)).catch(next);
};
}2. Feature Structure
src/shared/utils/async-handler.ts
import { Request, Response, NextFunction } from "express";
export type AsyncRouteHandler = (
req: Request,
res: Response,
next: NextFunction
) => Promise<unknown>;
export function AsyncHandler(fn: AsyncRouteHandler) {
return function (req: Request, res: Response, next: NextFunction) {
Promise.resolve(fn(req, res, next)).catch(next);
};
}Usage Example
import { Request, Response, NextFunction } from "express";
import { AsyncHandler } from "..utils/async-handler";
export const registerUser = AsyncHandler(async (req: Request, res: Response, next: NextFunction) => {
/*
* business logic
* your actual code
*/
});