【问题标题】:MongoDB / EJS: How to make synchronous query and render result values in EJSMongoDB / EJS:如何在 EJS 中进行同步查询和渲染结果值
【发布时间】:2020-07-11 08:19:07
【问题描述】:

我在异步编程的概念上有点挣扎,希望有人提供帮助/指导。 基本上,我正在开发一个连接到 mongodb 数据库的 node.js Web 服务器。 我正在使用 EJS 生成 HTML 文件,如下所示。

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

这些值中的大部分(“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;

};

问题出在这里: HTML 文件中打印的值始终是用于变量初始化的值,例如变量“server_n”为 0。经过一番研究,我了解到这是因为 .find(...) 是一个异步函数,因此程序会立即执行指令“return server_n;”,这意味着在 HTML 文件上显示的值将为 0 和不是 12345。

我已经在 StackOverflow 中查看了其他问题,但我很难理解解决此问题的可能方法,我的意思是我不能是唯一一个遇到这个问题的人,对吧?

您能否提供一些关于如何解决此问题的基本解释?我仍在学习,其中很多概念仍然难以理解。

非常感谢。

【问题讨论】:

    标签: javascript node.js mongodb asynchronous callback


    【解决方案1】:

    是的,您说得对,问题是由于对查询数据库等异步操作处理不当造成的。那么如何解决呢?

    使用异步/等待:
    在 NodeJS 中有多种处理异步操作的选项,但是,我强烈建议使用 async/await,它在语法上干净且易于理解。
    简单来说,async/await 是一种指定和处理异步操作的方式。您使用async 关键字来指定函数是异步的,并使用await 关键字来等待异步操作。需要注意的一件事是,您只能在 async 函数中使用 await 关键字。你可以阅读更多关于 async/await here.
    如果您的 nodeJS 版本是 7.6 或更高版本,开箱即支持 async/await,但是,如果您使用的是较低版本且无法升级,您可以设置像 Babel 这样的构建工具来使用 javascript较新的 ECMAScript 规范支持的功能。

    当使用 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 });
    }); 
    

    【讨论】:

    • 您好,非常感谢您的回复。现在开始有点意思了。我做了更多的研究,尝试了你的代码,我想我神奇地让它工作了!我还有一个关于在 for 循环中使用 async 和 await 的问题。假设我有一个经典的 for(let i =0; i
    • 只要 for/loop 包含在异步函数中,在 for/loop 中使用 await 应该可以正常工作。但是,在 javascript 循环中使用 async/await 时,您需要注意一些问题,您可以查看此article,它详细解释了它。
    猜你喜欢
    • 2016-05-23
    • 2015-05-12
    • 1970-01-01
    • 2016-11-01
    • 2012-11-27
    • 2018-12-26
    • 1970-01-01
    • 2019-02-03
    • 2018-01-12
    相关资源
    最近更新 更多