I’m new to Promises and async/await programming and I am not sure I am getting it straight. I am creating an API in Nodejs, with Express, Mongoose and MongoDB. I have seen a lot of tutorials on how to deal with asynchronicity but all of them are about NodeJs projects where the routing and the DB query are in the same file. example:
const asyncMiddleware = fn => (req, res, next) => { Promise.resolve(fn(req, res, next)) .catch(next); }; router.get('/users/:id', asyncMiddleware(async (req, res, next) => { const something = await getSomethingFromDb({ id: req.params.id }) res.json(something); }));
However, for clarity purposes, I have separated the routing from the controller but I have serious doubts I have done it correctly. Here is my code:
router.js
const asyncMiddleware = fn => (req, res, next) => { Promise.resolve(fn(req, res, next)) .catch(next); }; router.get('/something/:id', asyncMiddleware(async (req, res, next) => { const answer = await somethingController.findById(req, res, next) }));
controller.js
exports.findById = async (req, res, next) => { const something = await Something.findById(req.params.id).exec(); res.send(something); };
I have tried to console.log() stuff to check what gets printed what, but I have realized, due to the awaiting part, this whole piece of code will wait for the query to finish. Is this well implemented? How can I test it?
Versions: NodeJs v10.16.3 Mongoose v5.7.1
Advertisement
Answer
Firstly you don’t need an “asyncMiddleware”. Let me give a full example of how you can separate routes and controllers, while keeping the controller async:
Controller
exports.findById = async (req, res, next) => { try{ const something = await Something.findById(req.params.id).exec(); return res.send(something); }catch(err){ return res.status(500).send({ message: err.message }) } };
You should wrap you async
calls in a try/catch block.
Route
You would then simply call your controller in your route like so:
router.get('/:id', Controller.findByID)
and that’s it. You don’t need any additional async
call on your route.
If you have middlewares your want to add you route you can do it like this:
//for single middleware router.get('/:id',somethingMiddle,Controller.findByID) //for multiple middleware router.get('/:id',[somethingMiddle, anotherMiddle],Controller.findByID)
Let me know if this helps