简体   繁体   中英

How to throw error from custom class nodejs

I'm trying to create a global error handler in node js with typescript. I have created some custom classes which extends error class something like this:-

custom class

export abstract class CustomError extends Error {
  abstract statusCode: number;
  abstract errorMessage: string;
  abstract data: unknown;
  constructor() {
    super();
    Object.setPrototypeOf(this, CustomError.prototype);
  }

  abstract serializeError(): { message: string; fields?: string }[] | string;
}

Bad request error class

import { StatusCodes } from 'http-status-codes';

import { CustomError } from './custom.error';

class BadRequestException extends CustomError {
  statusCode = StatusCodes.BAD_REQUEST;
  errorMessage: string;
  data: any;

  constructor(errorMessage?: string) {
    super();
    // set default value
    this.errorMessage = errorMessage || 'Bad Request';

    Object.setPrototypeOf(this, BadRequestException.prototype);
  }

  serializeError() {
    return this.errorMessage;
  }
}

export default BadRequestException;

server.js

dotenv.config();
const app: Express = express();

app.use('/', routes);
app.use(globalErrorHandler);
export default app;

routes.ts

import express from 'express';
import UserController from '../controller/user/user-controller';
import NotFoundException from '../exception/not-found-exception';
import authorizationMiddleware from '../middleware/authorization-middleware';

const router = express.Router();

// users routes
router.post('/user/create', UserController.createUser);
router.get('/user/profile/:key', UserController.getProfile);
router.get('/user/directus', UserController.getDirectUs);

router.use('*', () => {
  throw new NotFoundException();
});

export default router;

controller.ts

import { Request, Response } from 'express';
import { StatusCodes } from 'http-status-codes';
import { directus } from '../../config/directus-confgi';
import BadRequestException from '../../exception/bad-request-exception';
import { USER } from '../../interface/user-interface';
import UserService from './user.service';

class UserController {
 
  // getting user profile
  static async getDirectUs(request: Request, response: Response) {
    try {
      const user = await directus.items('articles').readOne(15);

      response.status(StatusCodes.OK).json({ user });
    } catch (error: any) {
      throw new BadRequestException(error.message);
    }
  }
}

export default UserController;

Global Error Handler

import { StatusCodes } from 'http-status-codes';
import { Request, Response, NextFunction } from 'express';
import { CustomError } from '../exception/custom.error';

const globalErrorHandler = (err: any, req: Request, res: Response,next:NextFunction) => {
  if (err instanceof CustomError) {
    const error: { message: string; errors?: any } = {
      message: err.errorMessage ? req.body.i18nObj.__(err.errorMessage) : '',
    };

    if (err.data) error.errors = err.serializeError();

    return res.status(err.statusCode).json(error);
  }

  res.status(StatusCodes.INTERNAL_SERVER_ERROR).json({
    message: err.message
      ? err.message
      : req.body.i18nObj.__('MESSAGES.UNABLE_COMPLETE_REQUEST'),
    error: { message: err.message, err },
  });
};

export default globalErrorHandler;


I'm getting errors in my controller catch block and bad-request error class but after that my global error handler middleware function is not able to get this error, in a result, I'm not able to send this error as a response.

I don't know what I'm doing wrong or how can call my middleware function without throwing an actual error from the controller I want to use my custom error class to formate error and status code.

In Express v4, you need to manually call next() in async controllers in order for error handling middleware to work.

Catching Errors

For errors returned from asynchronous functions invoked by route handlers and middleware, you must pass them to the next() function, where Express will catch and process them.

class UserController {
  // getting user profile
  static async getDirectUs(
    request: Request,
    response: Response,
    next: NextFunction
  ) {
    try {
      const user = await directus.items("articles").readOne(15);

      response.status(StatusCodes.OK).json({ user });
    } catch (error: any) {
      // pass the custom error to `next()`
      next(new BadRequestException(error.message));
    }
  }
}

From Express v5 you won't have to do this

Starting with Express 5, route handlers and middleware that return a Promise will call next(value) automatically when they reject or throw an error

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM