简体   繁体   中英

MongoDB / EJS: How to make synchronous query and render result values in EJS

I'm struggling a little bit with the concepts of asynchronous programming and I would appreciate some help/guidance from someone. Basically, I'm developing a node.js web server that's connected to a mongodb database. I'm using EJS to generate HTML files as you can see below.

app.get("/", function(req, res){
    res.render('home', {date: getData.todaysDate(), n: getData.todaysIncidents(), nTot: getData.totalIncidents()});
}); 

Most of these values ('n' and 'nTot') are obtained by querying my database and then doing some other operations, as you can see in the following example code sample.

//------getData.js------//
exports.todaysIncidents = function() {
let server_n = 0;
Incident.find({dia: {$gt:y}}, function(err, result) {
    if (err) {
        console.log(err);
    } else{
        //do some stuff...
        server_n = 12345
        }
    }
});
return server_n;

};

Here is the problem: The values printed in the HTML file are always those used for variable initialization, such as 0 for variable 'server_n'. After doing some research, I understand that this happens because .find(...) is an asynchronous function so the program executes right away the instruction "return server_n;", which means that on the HTML file the value showed will be 0 and not 12345.

I already looked at other questions here in StackOverflow, but I'm struggling to understand a possible fix to this issue, I mean I can't be the only one going through this, right?

Could you please provide some basic explanation of how I could go around this issue? I'm still learning and a lot of these concepts remain hard to understand.

Thank you very much.

Yes, you are right that the problem is as a result of improper handling of asynchronous operations like querying the DB. So how do you fix it?

Using async/await:
There are multiple options to handle asynchronous operations in NodeJS, however, I would strongly recommend using async/await, it's syntactically clean and easy to understand.
To put it simply, async/await is a way of specifying and dealing with asynchronous operations. You use the async keyword to specify that a function is asynchronous, and you use the await keyword to wait for an asynchronous operation. One key thing to note is that you can only use the await keyword inside an async function. You can read more about async/await here .
If your nodeJS version is 7.6 or higher, async/await is supported out of the box, however, if you are using a lower version and can't upgrade, you can set up build tools like Babel to be able to use javascript features supported in newer ECMAScript spec.

When using async/await, your code should be something like this.:

//------getData.js------//
// NOTE: the typeof todaysIncidents is not more the regular function, 
// it's now an AsyncFunction because of the async keyword
exports.todaysIncidents = async function () {
  let server_n = 0;
  try {
    // In simple terms, the await keyword here would ensure that the DB query
    // resolves or reject before moving on to the next statement
    const incident = await Incident.find({ dia: { $gt: y } });
    // The incident variable stores the result of the query
    server_n = 12345
  } catch (err) {
    // Handle error from the DB query
    console.log(err);
  }
  return server_n;
};

.

//------The router------//
// NOTE: You also need to make the route handler an AsyncFunction
app.get("/", async function (req, res) {
  // You can await the differeint DB queries in here to ensure they resolve(or reject) before rendering the view
  const todaysDate = await getData.todaysDate();
  const todaysIncidents = await getData.todaysIncidents();
  const totalIncidents = await getData.totalIncidents();
  res.render('home', { date: todaysDate, n: todaysIncidents, nTot: totalIncidents });
}); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM