Skip to content

Issue: Refactor Backend to Implement catchAsync and Improve Error Handling #134

Description

@PorePranav

Is this a unique feature?

  • I have checked "open" AND "closed" issues and this is not a duplicate

Is your feature request related to a problem/unavailable functionality? Please describe.

Description

The current backend implementation uses try-catch blocks for error handling, which can lead to repetitive code and reduced readability. I propose refactoring the backend to use a catchAsync approach, implement a global error handler, and introduce custom AppError classes. This will improve code maintainability, readability, and consistency in error handling across our application.

Proposed Changes

  1. Implement a catchAsync utility function
  2. Refactor existing controllers to use catchAsync
  3. Create an errorController for centralized error handling
  4. Implement a global error handling middleware
  5. Introduce an AppError class for custom application errors

Proposed Solution

Implementation Details

1. catchAsync Utility Function

Create a new file utils/catchAsync.js:

const catchAsync = (fn) => {
  return (req, res, next) => {
    fn(req, res, next).catch(next);
  };
};

module.exports = catchAsync;

2. Refactor Controllers

Refactor existing controllers to use the catchAsync approach. For example, the createQuiz function would be refactored as follows:

const catchAsync = require('../utils/catchAsync');
const AppError = require('../utils/appError');

const createQuiz = catchAsync(async (req, res, next) => {
  const zodResult = validations.quizSchema.safeParse(req.body);

  if (!zodResult.success) {
    const errors = zodResult.error.errors.map((err) => err.message).join(', ');
    return next(new AppError(errors, 400));
  }

  let { title, questions, timeLimit } = zodResult.data;
  let quiz_id = generateUniqueId({
    length: 10,
    useLetters: true,
    useNumbers: true,
  });

  const user = await User.findById(req.user.id);
  quiz_id = user.username + '_' + quiz_id;

  let existingQuiz = await Quiz.findOne({ quiz_id });
  if (existingQuiz) {
    return next(new AppError('Quiz ID already exists', 400));
  }

  const newQuiz = new Quiz({
    title,
    quiz_id,
    questions,
    createdBy: req.user.id,
    timeLimit,
  });

  const quiz = await newQuiz.save();
  res.status(201).json(quiz);
});

module.exports = { createQuiz };

3. Error Controller

Creating a new file controllers/errorController.js as a middleware to process all App Errors

4. Global Error Handling Middleware

In your main application file index.js, adding the global error handling middleware

5. AppError Class

Create a new file utils/appError.js as a custom AppError class to throw errors

Benefits

  1. Improved code readability and maintainability
  2. Consistent error handling across the application
  3. Centralized error processing and formatting
  4. Easier debugging and error tracing

Next Steps

  1. Implement the proposed changes
  2. Update existing controllers to use the new error handling approach
  3. Test thoroughly to ensure all error scenarios are properly handled

Please review this proposal and provide any feedback or suggestions for improvement. If everything seems okay, kindly assign the issue so that I can start working

Screenshots

No response

Do you want to work on this issue?

Yes

Metadata

Metadata

Assignees

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions