I am using an AsyncHandler
wrapper function to catch my errors in my controller and service layer.
I am using next()
parameter to raise an error, and then catch it in my global error handler.
My global error handler is executing but my controller is also returning, even though it should haven’t return anything after error is thrown.
My Controller layer:
const categoryCtrl = {
create: asyncHandler( async (req, res, next) => {
const data = await CategoryService.createCategory("", 4, next)
return successResponse({res, data:data, msg:"Category created Successfully"})
}),
getAll: async (req, res, next) => {},
getById: async (req, res, next) => {},
delete: async (req, res, next) => {},
update: async (req, res, next) => {},
};
My service layer:
const categoryService = {
createCategory: async (data, x, next) => {
if (data === "") {
console.log("condition");
const err = new CustomError(404, "Wrong input");
return next(err);
} else {
return data;
}
},
};
My asyncHandler :
const asyncHandler = (func) => {
return (req, res, next) => {
try {
func(req, res, next)
} catch (error) {
next(error)
}
};
};
My successReponse
:
module.exports = ({res, msg, data}) => {
return res.status(200).json({msg:msg, data: data})
}
I have tried to use throw
, but I am trying to avoid try-catch block in my controller layer and service layer and raise error only throw using next()
parameter.
3
Answers
It looks like the
asyncHandler
is not correctly handling the asynchronous nature of the operations inside it. Specifically, it does not await the completion of thefunc
it wraps.You can modify your
asyncHandler
to properly handle asynchronous functions like thisThis asyncHandler now explicitly handles the promise returned by the func.
Update your controller by this
Update your service layer by this
That would have been the correct approach. If you want to use exceptions, you actually have to use them! Notice that you don’t actually need a
try
/catch
in your controller, that’s precisely what theasyncHandler
is doing for you. Notice that if you weren’t using exceptions, you would have to return an error code (e.g.null
instead of adata
object) from the service, and explicitly check that in your controller so that you returnsuccessResponse
conditionally. You don’t want that – only exceptions can achieve the goal of not requiring extra syntax in intermediate layers between the service andasyncHandler
.Using