Day 4 - 60 Days of Learning 2025


Creating an Asynchronous Request Handler and Custom Classes for API Errors and Responses
On June 4, 2025, I write an asynchronous request handler and custom classes for API error and response. The goal was to make some utilities that will eventually help me to write less redundant and consistent code.
The GitHub link for the repository of beats-backend service.
Asynchronous Request Handler
This utility function helps me to write the request handler functions in less redundant way, as it reduces the use of try…catch
statements. I can handle request and errors effectively and correctly.
import { Request, Response, NextFunction } from "express";
type Handler = (
req: Request,
res: Response,
next: NextFunction
) => Promise<any> | void;
const asyncHandler = (handler: Handler) => {
return (req: Request, res: Response, next: NextFunction) => {
return Promise.resolve(handler(req, res, next)).catch(next);
};
};
export { asyncHandler };
Usage Example
// Without asyncHandler
app.get("/user/:id", async (req, res, next) => {
try {
const userId = req.params;
const user = await User.findByID(userId);
...
} catch (error) {
next(error)
}
});
// With asyncHandler
app.get("/user/:id", asyncHandler(async (req, res) => {
const userId = req.params;
const user = await User.findByID(userId);
...
}));
APIError Class
This custom class helps to send back error response in a specified standard format throughout the project.
class APIError extends Error {
statusCode: number;
data: Record<string, any> | null;
errors: string[];
success: boolean;
constructor(
statusCode: number,
message: string = "Something went wrong",
data: Record<string, any> | null = null,
errors: string[] = []
) {
super(message);
this.name = this.constructor.name;
this.statusCode = statusCode;
this.data = data;
this.errors = errors;
this.success = false;
Error.captureStackTrace(this, this.constructor);
}
toJSON() {
return {
statusCode: this.statusCode,
message: this.message,
data: this.data,
errors: this.errors,
success: this.success,
};
}
}
export { APIError };
Usage Example
// Handle undefined routes
app.use((_, res: Response) => {
res.status(404).json(new APIError(404, "This route is not defined"));
});
Error Response Example
{
"statusCode": 404,
"message": "This route is not defined",
"data": null,
"errors": [],
"success": false
}
APIResponse Class
This custom class helps to send back API response in a specified standard format throughout the project.
class APIResponse {
statusCode: number;
message: string;
data: Record<string, any> | null;
success: boolean;
constructor(
statusCode: number,
message: string,
data: Record<string, any> | null = null
) {
this.statusCode = statusCode;
this.message = message;
this.data = data;
this.success = statusCode < 400;
}
toJSON() {
return {
statusCode: this.statusCode,
message: this.message,
data: this.data,
success: this.success,
};
}
}
export { APIResponse };
Usage Example
// Root route
app.get("/", (_, res: Response) => {
res
.status(200)
.json(
new APIResponse(200, "The backend service for Beats is up and running")
);
});
API Response Example
{
"statusCode": 200,
"message": "The backend service for Beats is up and running",
"data": null,
"success": true
}
After this I’m going to work on creating the models for some of the key entities of the project.
Subscribe to my newsletter
Read articles from Ashmin Bhujel directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Ashmin Bhujel
Ashmin Bhujel
Learner | Software Developer | TypeScript | Node.js | React.js | MongoDB | Docker