The async function to wrap (route handler or middleware)
Express middleware function that handles async errors
// Wrapping an async route handler
import { asyncHandler } from '@/shared/middleware/errorHandler';
router.get('/courses/:id', asyncHandler(async (req, res) => {
const course = await courseService.findById(req.params.id);
if (!course) {
throw new AppError('Course not found', 404, 'NOT_FOUND');
}
res.json({ data: course });
}));
// Wrapping async middleware
const validateCourse = asyncHandler(async (req, res, next) => {
const course = await prisma.course.findUnique({
where: { id: req.params.courseId }
});
if (!course) {
throw new AppError('Course not found', 404, 'NOT_FOUND');
}
req.course = course;
next();
});
// Wrapping a controller method
class UserController {
static getUser = asyncHandler(async (req, res) => {
const user = await userService.findById(req.params.id);
res.json({ data: user });
});
}
// Without asyncHandler (manual error handling required):
router.post('/users', async (req, res, next) => {
try {
const user = await userService.create(req.body);
res.status(201).json({ data: user });
} catch (error) {
next(error); // Manual error forwarding
}
});
// With asyncHandler (automatic error handling):
router.post('/users', asyncHandler(async (req, res) => {
const user = await userService.create(req.body);
res.status(201).json({ data: user });
})); // Errors automatically forwarded to error handler
Async Handler Wrapper for Express Route Handlers
A utility function that wraps asynchronous Express route handlers and middleware to ensure that any rejected promises or thrown errors are properly caught and passed to the Express error handling middleware. This wrapper eliminates the need for manual try-catch blocks in async route handlers and ensures consistent error handling across the application.
This function is particularly important for the WayrApp backend as it heavily uses async operations for database queries, external API calls, and file operations. Without proper error handling, unhandled promise rejections could crash the application or leave requests hanging without responses.
The asyncHandler works by wrapping the provided async function in a Promise.resolve() call and attaching a .catch() handler that forwards any errors to the Express error handling middleware via the next() function. This ensures that all errors, whether thrown synchronously or from rejected promises, are properly handled by the errorHandler middleware.
This utility supports the application's distributed architecture by ensuring reliable error handling across all async operations, which is critical for maintaining system stability and providing consistent error responses to clients across multiple nodes and services.
Key Benefits:
How It Works:
Usage Patterns: