//creating a route for http://127.0.0.1:8080/Work
app.get('/Work', function(req, res){
//connect to my first collection
db.collection('my-collection1').find().each( function (err,doc) {
//if there's an error
if(err) throw err;
//if there is no more docs
if (!doc) {
console.dir("No document found");
return db.close();
//return;
}
//...do stuff here to your docs here to get a value for x
});
//write to the Work.html file in your/views directory and pass it the variable x
return res.render('Work', { "x" : x });
//connect to my 2nd collection
db.collection('my-collection2').find().each( function (err,doc) {
//if there's an error
if(err) throw err;
//if there is no more docs
if (!doc) {
console.dir("No document found");
return db.close();
//return;
}
//...do stuff here to your docs here to get a value for y
});
//write to the Work.html file in your/views directory and pass it the variable x
return res.render('Work', { "y" : y });
});
使用上面的代码,我要做的是连接到MongoDB中的2个集合,并使用express框架将它们渲染到我的/ views /目录中的网页文件。
我的views目录中的html文件如下所示:
<html>
<h6>Hello there.</h6>
<h6>Value of x is: {{x}} </h6>
<h6>Value of y is: {{y}} </h6>
<html>
现在我的问题是要显示x和y。现在这可能是由于我对回调和异步函数缺乏了解,我稍微理解了这一点。
基于我提供的内容,有人可以建议我如何实现我想要的功能,同时还可以解释回调和异步功能?也许我的方法是完全错误的连接到这样的2个集合? tks
注意:这些是自己工作的(如果我在自己的单独页面上显示它们),这里我试图将x和y放在一起并显示在一页上。
答案 0 :(得分:0)
第一个问题是,只要您致电return res.render('Work', { "x" : x });
,您的功能就会终止,而且计算y
的代码部分永远不会被执行。
我还假设您在x
函数的范围之上声明了变量y
和GET
,并且存储了值?如果没有,你应该这样做,以使他们的范围更明确。
你也在调用db.close()
,这不是必需的,因为你只是停留在同一个数据库中而只是切换集合,所以从性能的角度来看,你只想继续使用相同的连接计算(连接池将在引擎盖下进行)。
您的代码正在执行的异步说明:
将这些问题排除在外,调用的异步性质意味着你的函数(计算x的函数和计算y的函数)是并行执行的(即同时执行),并且因为你如果没有res.render
和x
,我们不知道在y
拨打render
之前哪个完整。 200 OK
函数只能在Express中调用一次,因为在调用它时会将结果发送回用户的浏览器并发送x
HTTP响应,并结束与Node webserver的连接。
因此,您的基本问题归结为需要保证已完成计算完成y
和x
,然后仅将一个响应发送回网络浏览器。
您有两种选择来解决这个问题:
将它们转换为串行函数调用 - 即调用计算y
的函数,等待它完成,然后再调用计算return res.render('Work', { "x" : x, "y" : y });
的函数,然后渲染结果。这就是回调的用武之地。请注意,这种方法可能比以异步方式进行两种计算要慢,因为您迫使第二步等待可能耗费时间的过程才能完成甚至可以启动。< / p>
异步运行两个计算,当它们终止时,它可以检查另一个计算是否也已完成。无论哪一个完成第二个,都会调用x
,并知道y
和y
已填充了您想要的结果。你需要执行这个wat
选项1 使用回调看起来像这样(请注意,x
的计算仅在没有其他文档要处理以计算//creating a route for http://127.0.0.1:8080/Work
app.get('/Work', function(req, res){
//connect to my first collection
db.collection('my-collection1').find().each( function (err,doc) {
if(err) throw err;
//...do stuff here to your docs here to get a value for x
//once there are no more docs, initiate the calculation for y
if (!doc) {
console.dir("No document found");
db.collection('my-collection2').find().each( function (err,doc) {
if(err) throw err;
//...do stuff here to your docs here to get a value for y
//if there is no more docs, then we know that both x and y have been calculated
if (!doc) {
console.dir("No document found");
res.render('Work', { "x" : x, "y" : y });
}
}
}
});
});
时启动:)< / p>
x
还有各种各样的框架允许您在节点中以同步方式链接异步调用 - 检查streamline.js,这允许您使用下划线字符作为回调来更干净地进行链式方法,但是即使你使用这样一个库,它几乎可以转化为我上面的代码在幕后所做的事情。
选项2 (我的首选选项,因为它可能是更好的性能)只需通过检查计数器来检查y
和//creating a route for http://127.0.0.1:8080/Work
app.get('/Work', function(req, res){
var counter = 0;
//connect to my first collection
db.collection('my-collection1').find().each( function (err,doc) {
if(err) throw err;
//...do stuff here to your docs here to get a value for x
//once there are no more docs, add one to the counter
if (!doc) {
console.dir("No document found");
counter++;
if (counter == 2) {
res.render('Work', { "x" : x, "y" : y });
}
}
});
db.collection('my-collection2').find().each( function (err,doc) {
if(err) throw err;
//...do stuff here to your docs here to get a value for x
//once there are no more docs, add one to the counter
if (!doc) {
console.dir("No document found");
counter++;
if (counter == 2) {
res.render('Work', { "x" : x, "y" : y });
}
}
});
});
的计算是否已完成:< / p>
res.render
所以基本上,你可以并行执行两个计算,然后以第二个结束时调用{{1}}并发回响应。
请注意,我实际上没有测试上面的代码片段,但他们应该给你这个想法。