WayrApp Backend & Ecosystem Documentation - v1.0.0
    Preparing search index...

    Function asyncHandler

    • 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:

      • Eliminates boilerplate try-catch blocks in route handlers
      • Ensures all async errors are properly caught and forwarded
      • Maintains consistent error handling across the application
      • Prevents unhandled promise rejections that could crash the server
      • Works with both async/await and Promise-based code
      • Preserves function context and arguments

      How It Works:

      1. Wraps the provided function in Promise.resolve()
      2. Catches any errors (sync or async) using .catch()
      3. Forwards caught errors to Express error handling via next()
      4. Maintains the original function signature and return value

      Usage Patterns:

      • Route handlers that perform async operations
      • Middleware functions that need async error handling
      • Any Express function that uses async/await or returns promises

      Parameters

      • fn: Function

        The async function to wrap (route handler or middleware)

      Returns (req: Request, res: Response, next: NextFunction) => Promise<any>

      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
      // Handling database operations
      router.put('/users/:id', asyncHandler(async (req, res) => {
      const user = await prisma.user.update({
      where: { id: req.params.id },
      data: req.body
      });
      res.json({ data: user });
      })); // Prisma errors automatically caught and handled

      @function asyncHandler