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



我在异步编程的概念上有点吃力,希望有人能给我一些帮助/指导基本上,我正在开发一个连接到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中研究了其他问题,但我很难理解这个问题的可能解决方案,我的意思是,我不可能是唯一一个经历这个问题的人,对吧?

你能为我如何解决这个问题提供一些基本的解释吗?我还在学习,很多这些概念仍然很难理解。

非常感谢。

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

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

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

最新更新