Teambit
Teambit

Reputation: 325

Node + Express - Getting dbData before the render

I am trying to render a view with a table of data fetched from a local db. The query and all data checks out in the format I want. But before the data is fetched, the view is rendered, and i get an error.

This is my route.js where I would expect the error to be found.

exports.getIndex = (req, res) {
  const result = sqldb.GetSubscribers()
  try{
      res.render('subscribtions/index', {
        moment: moment,
        subs : result,
        pageTitle: 'Subscribtions',
        path: '/subscribtions'
        })
      }
  catch(error)
      {
        console.log(error)
        res.redirect(404, '../views/404.ejs');
      }
}; 

DBcall just for orientation

exports.GetSubscribers = function() {
    const connString = "ConnectionString";

    query = "Some Long Query" 

    sql.open(connString, (err, con) => {
        if (err) {
        console.log('failed to open ' + err.message)
        }
        con.prepare(query, (err, ps) => {
            if (err) {
                console.log('Fejl - prepare: '+err.message)
                return
            }
            con.query(query, (err, rows) => {
                if (err) {
                    console.log('Fejl - query: '+ err.message)
                    return err;
                }
                console.log("Returning results...")
                return rows;
            })
        })
    })
}

So far I have been trying to work out how to use async/await or Promise, but without any luck. Can any of you brilliant minds point me in the right direction?

Upvotes: 1

Views: 136

Answers (1)

Christian
Christian

Reputation: 7852

The reason is probably that the db call is async and since you don't await it it will return the rendered view before the data has been fully fetched.

Thus you need to await the call to the database. Given that the function is awaitable:

exports.getIndex = async (req, res) => {
  ...
  try {
     const result = await sqldb.GetSubscribers();
  }
  catch(err) {
     console.log('Error getting subscribers', err);
  }
  ...
};

Alternatively, if the function is then-able:

exports.getIndex = (req, res) => {
  return sqldb.GetSubscribers().then(result => 
    res.render('subscribtions/index', {
      moment: moment,
      subs : result,
      pageTitle: 'Subscribtions',
      path: '/subscribtions'
    })
  .catch(error => {
    console.log(error);
    res.redirect(404, '../views/404.ejs');
  }));
}

To make the GetSubscribersfunction return a promise:

exports.GetSubscribers = () => {
  const connString = 'ConnectionString';

  query = 'Some Long Query';

  return new Promise((resolve, reject) => {
    sql.open(connString, (err, con) => {
      if (err) {
        console.log(`failed to open ${err.message}`);
      }
      con.prepare(query, (err, ps) => {
        if (err) {
          console.log(`Fejl - prepare: ${err.message}`);
          reject();
        }
        con.query(query, (err, rows) => {
          if (err) {
            console.log(`Fejl - query: ${err.message}`);
            reject(err);
          }
          console.log('Returning results...');
          resolve(rows);
        });
      });
    });
  });
};

Upvotes: 2

Related Questions