javascriptexpressmongojs

Express not awaiting MongoJS Function


I've set up a function for my Express JS endpoint to 'await' to get a result from a Mongo DB using Mongo JS.

Function:-

async function getIntroducer(company){


  const intro = await dbIntro.collection('introducers').findOne({company: company},  function(err, doc) {
 
 console.log("šŸš€ ~ file: app.js ~ line 289 ~ intro ~ doc.introducer", doc.introducer)
   return doc.introducer
  });
  
  
  return intro

  //return intro;
};

Express JS Endpoint:-

app.post(
  "/case",
  passport.authenticate("accessToken", { session: false }),
  async function (req, res) {
    const body = req?.body;
    
    const intro = await getIntroducer(req.user.company);
    console.log("šŸš€ ~ file: app.js ~ line 1152 ~ intro", intro)

Current behaviour, :-


šŸš€ ~ file: app.js ~ line 1152 ~ intro undefined

Then the result sends, then thereafter I get this in console (aka it's not awaiting):-


šŸš€ ~ file: app.js ~ line 289 ~ intro ~ doc.introducer 347501

I've also tried completely getting rid of 'const intro' and just straight returning it. And I've also tried getting rid of the callback function but MongoJS says 'CB is not a function'

Any help please?


Solution

  • You're mincing different styles of asynchronous implementations (callback and promise) when querying the collection.

    Seeing as the mongojs library supports only the callback style. You need to promisify the findOne operation to await it.

    There is the promisify function in the util standard library module that can aid in this goal inasmuch as the callback signature is a function that is called with an error and/or a result.

    For example, to promisify the findOne operation so that it can be awaited, you can write

    const util = require('util');
    
    async function getIntroducer(company){
      const findOneDbIntro = util.promisify(dbIntro.collection('introducers').findOne);
      let intro;
      try {
        intro = await findOneDbIntro({company: company});
      }
      catch (err) 
      {
        // log error with your logging library.
      }
    //...
    }
    

    This gives a similar result to doing by hand. The Promise object is well documented on MDN:

    async function getIntroducer(company){
      let intro;
      try {
        intro = await new Promise(
          (resolve, reject) => {
            dbIntro.collection('introducers').findOne({company: company},
              function (err, doc) {
              if(err) {
                reject(err);
              }
              resolve(doc);
           });
        });
      } catch (err) 
      {
        // log error with your logging library.
      }
        //...
    }