Skip to content
Advertisement

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

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

Advertisement