Async/await In Nodejs + Mongoose
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
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();
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
Related Questions
- → How to update data attribute on Ajax complete
- → October CMS - Radio Button Ajax Click Twice in a Row Causes Content to disappear
- → Octobercms Component Unique id (Twig & Javascript)
- → Passing a JS var from AJAX response to Twig
- → Laravel {!! Form::open() !!} doesn't work within AngularJS
- → DropzoneJS & Laravel - Output form validation errors
- → Import statement and Babel
- → Uncaught TypeError: Cannot read property '__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED' of undefined
- → React-router: Passing props to children
- → ListView.DataSource looping data for React Native
- → Can't test submit handler in React component
- → React + Flux - How to avoid global variable
- → Webpack, React & Babel, not rendering DOM