-1

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);
        })
    })
};
alexis
  • 31
  • 6
  • You aren't showing us enough of your code for us to advise properly. For example, you show a function call `search(req.user)` which is the only function other than `next()` that you call in the middleware, but you don't show us the code for that. We need to see that. Also, you define `getInfo()`, but don't show any place that it is called. – jfriend00 Jul 10 '18 at 06:41
  • And, please format your code with proper indentation to make it easier to read the code. – jfriend00 Jul 10 '18 at 06:42
  • I meant getInfo() instead of search() before return next)();. I edited it – alexis Jul 10 '18 at 06:45
  • Also you don't need to see the info.search(user); code. It's just to retrieve results from the database. – alexis Jul 10 '18 at 06:46
  • Does `info.search()` return a promise that resolves to the desired result? If not, `await` won't get you the result. I'd suggest not telling us what we do and don't need to see. Many problems here are because of wrong assumptions by the questioner so we need to test those assumptions and the absolute fastest and surest way is for us to see all relevant code. – jfriend00 Jul 10 '18 at 06:47
  • I'm sorry.. added it, thank you – alexis Jul 10 '18 at 06:52
  • OK, I updated my answer in a couple of ways. Hopefully that explains things to you. – jfriend00 Jul 10 '18 at 06:57

1 Answers1

0

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});
};
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • @alexis - I added a simpler and fixed version of your search function (the benefit of showing us the code). – jfriend00 Jul 10 '18 at 06:54
  • @Alexis - Does this explain it for you? If so, you can indicate that to the community by clicking the checkmark to the left of the answer and also you will earn some reputation points for following the proper procedure on stack overflow. – jfriend00 Jul 10 '18 at 07:17