Search code examples
node.jsexpressmiddleware

node.js middleware making code synchronous


I am trying to make res.locals.info available on every single page. I'm trying to do this by middleware but I'm getting an error. Apparently res.locals.info is not ready yet when the page render, thus I get an error info is not defined. How do I solve this?

  app.use(function(req,res,next){

  async function getInfo(user) {

    let result = await info.search(user);
    setInfo(result);
  }

function setInfo(result){

  res.locals.info= result;
}
getInfo(req.user);

  return next();
})

search():

module.exports.search= function (user) {
    var query=`SELECT count(*) as Info from dbo.InfoUsers WHERE user= '${user}' ;`

    return new Promise((resolve, reject) => {
    sequelize
        .query(`${query}`, {model: InformationUser})
        .then((info) => {

        resolve(info);
        })
    })
};

Solution

  • You were calling next() before your getInfo() function had done its work, thus res.locals.info had not yet been set when you were trying to use it.

    An async function returns a promise. It does NOT block until the await is done. Instead, it returns a promise immediately. You will need to use await or .then() on getInfo() so you know when it's actually done.

    If info.search() returns a promise that resolves to the desired result, then you could do this:

    app.use(function(req,res,next){
    
      // this returns a promise that resolves when it's actually done
      async function getInfo(user) {
        let result = await info.search(user);
        setInfo(result);
      }
    
      function setInfo(result){
        res.locals.info= result;
      }
    
      // use .then() to know when getInfo() is done
      // use .catch() to handle errors from getInfo()
      getInfo(req.user).then(result => next()).catch(next);
    
    });
    

    And, you can remove the deferred anti-pattern from your search function and fix the error handling (which is a common issue when you use the anti-pattern). There is no need to wrap an existing promise in another promise.:

    module.exports.search = function (user) {
    
        var query=`SELECT count(*) as Info from dbo.InfoUsers WHERE user= '${user}' ;`
        // return promise directly so caller can use .then() or await on it
        return sequelize.query(`${query}`, {model: InformationUser});
    };