简体   繁体   English

MongoDB / EJS:如何在 EJS 中进行同步查询和呈现结果值

[英]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.基本上,我正在开发一个连接到 mongodb 数据库的 node.js Web 服务器。 I'm using EJS to generate HTML files as you can see below.我正在使用 EJS 生成 HTML 文件,如下所示。

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.大多数这些值('n' 和 'nTot')是通过查询我的数据库然后执行一些其他操作获得的,如下面的示例代码示例所示。

//------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'.问题在于: HTML 文件中打印的值始终是用于变量初始化的值,例如变量 'server_n' 为 0。 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.在做了一些研究后,我明白这是因为 .find(...) 是一个异步函数,所以程序立即执行指令“return server_n;”,这意味着在 HTML 文件中显示的值将是 0 和不是 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?我已经在 StackOverflow 中查看了其他问题,但我正在努力理解这个问题的可能解决方案,我的意思是我不可能是唯一一个经历这个的人,对吧?

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.在 NodeJS 中有多种处理异步操作的选项,但是,我强烈建议使用 async/await,它在语法上干净且易于理解。
To put it simply, async/await is a way of specifying and dealing with asynchronous operations.简单来说,async/await 是一种指定和处理异步操作的方式。 You use the async keyword to specify that a function is asynchronous, and you use the await keyword to wait for an asynchronous operation.使用async关键字指定函数是异步的,使用await关键字等待异步操作。 One key thing to note is that you can only use the await keyword inside an async function.需要注意的一个关键事项是您只能在async函数中使用await关键字。 You can read more about async/await here .您可以在此处阅读有关 async/await 的更多信息。
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.如果您的 nodeJS 版本是 7.6 或更高版本,async/await 是开箱即用的,但是,如果您使用的是较低版本且无法升级,则可以设置像Babel这样的构建工具来使用支持的 javascript 功能在较新的 ECMAScript 规范中。

When using async/await, your code should be something like this.:使用 async/await 时,您的代码应该是这样的:

//------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 });
}); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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