MongoDB / EJS:如何在EJS中进行同步查询和渲染结果值
MongoDB / EJS: How to make synchronous query and render result values in EJS
我在异步编程的概念上遇到了一些困难,我希望有人能提供一些 help/guidance。
基本上,我正在开发一个连接到 mongodb 数据库的 node.js 网络服务器。
我正在使用 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。
我已经在 Whosebug 中查看了其他问题,但我正在努力了解解决此问题的可能方法,我的意思是我不可能是唯一一个遇到这个问题的人,对吗?
您能否就我如何解决此问题提供一些基本解释?我还在学习,其中很多概念仍然难以理解。
非常感谢。
是的,您是对的,问题是由于对查询数据库等异步操作处理不当造成的。那么如何解决呢?
使用async/await:
在 NodeJS 中有多种处理异步操作的选项,但是,我强烈建议使用 async/await,它在语法上干净且易于理解。
简单来说,async/await是一种指定和处理异步操作的方式。您使用 async
关键字来指定一个函数是异步的,您使用 await
关键字来等待异步操作。需要注意的一件重要事情是,您只能在 async
函数中使用 await
关键字。您可以阅读更多关于 async/await here.
如果您的 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 });
});
我在异步编程的概念上遇到了一些困难,我希望有人能提供一些 help/guidance。 基本上,我正在开发一个连接到 mongodb 数据库的 node.js 网络服务器。 我正在使用 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。
我已经在 Whosebug 中查看了其他问题,但我正在努力了解解决此问题的可能方法,我的意思是我不可能是唯一一个遇到这个问题的人,对吗?
您能否就我如何解决此问题提供一些基本解释?我还在学习,其中很多概念仍然难以理解。
非常感谢。
是的,您是对的,问题是由于对查询数据库等异步操作处理不当造成的。那么如何解决呢?
使用async/await:
在 NodeJS 中有多种处理异步操作的选项,但是,我强烈建议使用 async/await,它在语法上干净且易于理解。
简单来说,async/await是一种指定和处理异步操作的方式。您使用 async
关键字来指定一个函数是异步的,您使用 await
关键字来等待异步操作。需要注意的一件重要事情是,您只能在 async
函数中使用 await
关键字。您可以阅读更多关于 async/await here.
如果您的 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 });
});