0

I am trying to make a query in three collections then send the results (from all three collections) to my view engine. I have the code that works but it does not look efficient. It is very nested and hard to understand. I would like to make it clean and efficient. I am also wondering how I can catch all the error at once. The following is the code:

    exports.getEditContent = (req, res) => {

  Message.findById(req.params.id) //first query
    .populate({
      path: 'individual',
      model: PersonServed,
      select: 'shortName _id'
    })
    .populate({
      path: 'participants',
      model: User,
      select: 'shortName firstName _id'
    })
    .then(draft => {

      User.find({}) //second query
        .populate({
          path: 'program',
          model: Program,
          select: 'name'
        })
        .then(participantList => {
          PersonServed.find({}) //third query
            .populate({
              path: 'program',
              model: Program,
              select: 'name'
            })
            .then(individualList => { //all the results are used here
              res.render('message/editDraft', {
                pTitle: 'New Message',
                participantList: participantList,
                individualList: individualList,
                draft: draft,
                csrfToken: req.csrfToken()
              });
            }).catch(err => {
              req.flash('error_msg', 'An Error Occured While Processing your Request. Try Again Later.');
              res.redirect('/drafts');
            })
        })
        .catch(err => {
          req.flash('error_msg', 'An Error Occured While Processing your Request. Try Again Later.');
          res.redirect('/drafts');
        })
    })

}

Thank you

Yacin
  • 98
  • 2
  • 11

1 Answers1

0
exports.getEditContent = (req, res) => {

    Message.findById(req.params.id) //first query
        .populate({
            path: 'individual',
            model: PersonServed,
            select: 'shortName _id'
        })
        .populate({
            path: 'participants',
            model: User,
            select: 'shortName firstName _id'
        })
        .then(draft => {
            return User.find({}) //second query
                .populate({
                    path: 'program',
                    model: Program,
                    select: 'name'
                }).then(participantList => [participantList, draft])
        })
        .then(([participantList, draft]) => {
            return PersonServed.find({}) //third query
                .populate({
                    path: 'program',
                    model: Program,
                    select: 'name'
                }).then(individualList => [individualList, participantList, draft])
        })
        .then(([individualList, participantList, draft]) => { //all the results are used here
            res.render('message/editDraft', {
                pTitle: 'New Message',
                participantList: participantList,
                individualList: individualList,
                draft: draft,
                csrfToken: req.csrfToken()
            });
        })
        .catch(err => {
            req.flash('error_msg', 'An Error Occured While Processing your Request. Try Again Later.');
            res.redirect('/drafts');
        })

}

I used Promise chaining here which is basically chained .then statements and you can catch the error in the last block too.

async await version can be much neater:

exports.getEditContent = async (req, res) => {
    try {
        const draft = await Message.findById(req.params.id) //first query
            .populate({
                path: 'individual',
                model: PersonServed,
                select: 'shortName _id'
            })
            .populate({
                path: 'participants',
                model: User,
                select: 'shortName firstName _id'
            });
        const participantList = await User.find({}) //second query
            .populate({
                path: 'program',
                model: Program,
                select: 'name'
            });
        const individualList = await PersonServed.find({}) //third query
            .populate({
                path: 'program',
                model: Program,
                select: 'name'
            });
        res.render('message/editDraft', {
            pTitle: 'New Message',
            participantList: participantList,
            individualList: individualList,
            draft: draft,
            csrfToken: req.csrfToken()
        });
    } catch (err) {
        req.flash('error_msg', 'An Error Occured While Processing your Request. Try Again Later.');
        res.redirect('/drafts');
    }
}
Faizuddin Mohammed
  • 4,118
  • 5
  • 27
  • 51