0

I'm new to the Express, and I'm trying to apply some error handling at the top level.

This is how my project setup so far

In my controllers file, I have a controller to get all tours.

exports.getAllTours = async (req: Request, res: Response) => {
  //Execute query
  const features = new APIFeatures(Tour.find(), req.query)
    .filter()
    .sort()
    .limitFields()
    .paginate();

  // Endpoint: http://localhost:8000/api/v1/tours
  // Enter a wrong URL here will not even trigger the console.log function.
  // But I want to throw the error right here, not in the app.all('*')
  console.log("features", features);

  if (!features) {
    throw new NotFoundError("Tours Not Found");
  }

  //same problem here.
  const tours = await features.query;
  console.log("tours", tours.length);

  if (!tours) {
    throw new NotFoundError("Tours Not Found");
  }

  res.status(200).json({
    status: "success",
    result: tours.length,
    data: {
      tours,
    },
  });
};

I have a CustomError class that extends the Error class like this.

const httpStatusCode = require("./httpStatusCode");

class CustomError extends Error {
  constructor(message: string, statusCode: number, description: string) {
    super(description);

    //Object.setPrototypeOf(this, new.target.prototype);
    this.message = message;
    this.statusCode = statusCode;
  }
}
module.exports = CustomError;


class NotFoundError extends CustomError {
  constructor(message, statusCode) {
    super(message, statusCode);
    this.message = message;
    this.statusCode = httpStatusCode.NOT_FOUND;
  }
}

module.exports = NotFoundError;

Also an error handling middleware:

import { NextFunction, Request, Response, ErrorRequestHandler } from "express";

module.exports = (
  err: Error,
  req: Request,
  res: Response,
  next: NextFunction
) => {
  err.statusCode = err.statusCode || 500;
  err.status = err.status || "error";
  res.status(err.statusCode).json({
    status: err.status,
    message: err.message,
  });
};

In the end, I use the errorHandler middleware in the app to catch all the errors. However, the problem is all the errors in the getAllTours controller will not be thrown, instead, they will be thrown in the app.all():

app.use("/api/v1/tours", tourRouter);
app.all("*", (req: Request, res: Response) => {
  throw new NotFoundError("Page Not Found");
  //next(new AppError(`Can't find ${req.originalUrl} on this server`, 404));
});

app.use(errorHandler);

I know since the endpoint has been changed and thrown in the app.all() make sense. But how can I manually throw an error in the getAllTours controller? I use express-async-error so I could use the throw keyword in the async function.

  • _"Enter a wrong URL here will not even trigger the console.log function"_. What do you mean by that? What's a "wrong URL"? If you're using a URL that doesn't match the route, the handler won't get called _at all_. What is `tourRouter`, and for which route is `getAllTours` getting called? It seems very likely that your issue isn't with your error handling but with your route handling. – robertklep Sep 07 '22 at 10:14

1 Answers1

0

I figure it out.

Handle Express async error

I had no idea Express version 4 could not handle the async errors by simply throwing a new error. I'm still not sure if Express Version 5 as it now could handle it. But I use ExpressJS Async Errors to solve this issue in the end.