[Fixed] Express Mongoose throw custom error on callbacks

Issue

I’m trying to throw some custom error classes from mongoose callbacks.
Here is a simple code

const Restaurant = require('../models/Restaurant')
const { InternalServerError, UnauthorizedError } = require('../errors/errors')

const checkRestaurantAuthorization = async (token) => {

    const restaurant = Restaurant.findOne({ 'token': token }, function (error, result) {
        if (error) throw new InternalServerError()
        else if (!result) throw new UnauthorizedError()
        else return token
    })

}

In my code checkRestaurantAuthorization is called by a simple middleware like

const restaurantMidlleware = async (req, res, next) => {
    console.log('Request Type:', req.method);

    try {
        token = await checkRestaurantAuthorization('invalid_token')
        next()
    } catch (error) {
        next(error)
    }
}

Now if a restaurant instance with the given token is not found, the app crashes with throw er; // Unhandled 'error' event. From my testing it seems that executions stops when throw new UnauthorizedError() is called and I’m unable to identify the issue.

Here is also an example of a custom defined error if it’s useful

class UnauthorizedError extends Error {
    constructor(message) {
        super(message)
        this.name = 'Unauthorized request'
        this.code = 403
        Error.captureStackTrace(this, UnauthorizedError)
    }
}

What am I missing?

Solution

have you tried putting your first block in ‘try-catch’ block?

The throw statement throws a user-defined exception. Execution of the current function will stop (the statements after throw won’t be executed), and control will be passed to the first catch block in the call stack. If no catch block exists among caller functions, the program will terminate.

you can change code to promise or async-await

another source of the problem could be the fact that your are using async and callback in one function try to omit async then use it again

And there is no point in writing ‘const restaurant =’ in

const restaurant = Restaurant.findOne

since every found restaurant will be saved in callback’s result variable

try this

function checkRestaurantAuthorization(token){
return new Promise(async(resolve, reject)=>{

    try {
        const restaurant = await Restaurant.findOne({ 'token': token });
        if (!restaurant)
            return reject(new UnauthorizedError())
        else
            return resolve(token)
    }catch(error){
        return reject(new InternalServerError())
    }

})}

Even better approach would be using only async function with try-catch instead of returning a promise or any callback

Leave a Reply

(*) Required, Your email will not be published