简体   繁体   English

Node.js / MongoDB代码内的异步问题

[英]Asynchronous issue within nodejs/mongodb code

I am new to nodejs/express/mongodb/jade and I have been trying for some time now to put together a simple site to help facilitate a more efficient way of reaching back to past data and being able to reuse it quickly. 我是nodejs / express / mongodb / jade的新手,并且我一直在尝试一段时间以建立一个简单的站点,以帮助促进更有效的方式来恢复过去的数据并能够快速重用它。 I determined the easiest way to us it would be do have a dynamic URL and had started to make good progress and then ran into a road block. 我确定最简单的方法是使用动态URL,并开始取得良好进展,然后遇到障碍。

End Goal: I am looking to use the URL params to determine which data is returned. 最终目标:我正在寻找使用URL参数来确定返回哪些数据。 Ran locally the syntax would look like localhost/:collection/:id. 在本地运行语法类似于localhost /:collection /:id。 As an example it'd look like: localhost/lastyear/aug2001. 例如,它看起来像:localhost / lastyear / aug2001。 Thus the resulting page would display the data in the collection lastyear where the _ID is equal to aug2001. 因此,结果页面将显示去年集合中的数据,其中_ID等于aug2001。

To achieve this I currently I have the route in index.js set as: 为此,我目前将index.js中的路由设置为:

var express = require('express');
var router = express.Router();

router.get('/:collection/:id', function(req, res) {
    var db = req.db;
    var collection = db.get(req.params.collection);
    var entry = collection.findOne({ id: req.params.id },{})
    res.render('dataentry',{ title: 'Information for: ' + req.params.collection + ' ' + req.params.id +'.', data: entry
    });   
});

module.exports = router;

The structure of a doc within the collection looks as something as follows: 集合中的文档结构如下所示:

{
     "_id": "aug2001"
     "header": "header text"
     "content": "content text"
     "item" : "items text"
}

For testing to see some form of data my jade file for dataentry looks as follows(I know tabbing is important in jade and it may not look correct here in the post but I made sure the tabs are correct): 为了测试以查看某种形式的数据,我的jade文件用于dataentry的外观如下(我知道制表符在jade中很重要,在本文中看起来可能不正确,但我确保制表符正确):

block content 
     p Finding info...
     p= data.header
     p= data.content
     p= data.item

When navigating to /lastyear/aug2001 all I see is the page load "Finding info..." and I am not sure what I am missing as far as the jade syntax goes in order to display the doc data. 导航到/ lastyear / aug2001时,我看到的只是页面加载“ Finding info ...”,而且我不确定为了显示doc数据而在jade语法方面缺少什么。 I appreciate any help/suggestions of a more efficient way to achieve my end result. 我非常感谢您提供帮助/建议,以更有效的方式来达到最终结果。

EDIT: The real issue was not with JADE displaying but rather a asynchronous db call when pulling data out of the db. 编辑:真正的问题不是JADE显示,而是从数据库中提取数据时的异步数据库调用。

From what i see you have asynchronous problem here. 从我看来,您在这里有异步问题。

Try like this 这样尝试

router.get('/:collection/:id', function(req, res) {
   var db = req.db;
   var collection = db.get(req.params.collection);
   //this is async operation so you need to wait until it finish.
   //and only then send response to page.
   collection.findOne({ id: req.params.id },{}, function(err, entry){
      res.render('dataentry',{ title: 'Information for: ' + req.params.collection + ' ' + req.params.id +'.', data: entry
      });  
   }); 
});

Hope this helps. 希望这可以帮助。

Code not checked 代码未检查


As @Mykola Borysyuk mentioned, this seems to be an asynchronous callback problem. 如@Mykola Borysyuk所述,这似乎是一个异步回调问题。 In your code, collection.findOne({ id: req.params.id },{}) is an asynchronous function, so you have no idea when it will be executed. 在您的代码中, collection.findOne({ id: req.params.id },{})是一个异步函数,因此您不知道何时执行。 As you are rendering the page from outside the function callback, it would seem that entry is not modified before the rendering call occurs. 从函数回调外部渲染页面时,似乎在渲染调用发生之前未修改该条目。

As mentioned in the above answer, one way to do this is by creating a callback function, and rendering the page from inside the callback. 如上述答案中所述,一种方法是创建一个回调函数,并从回调内部渲染页面。 That would be as @Mykola showed. 就像@Mykola所示。 For sake of clarity, I'm giving it below. 为了清楚起见,我在下面给出。

var collection = db.collection(req.params.collection);
   collection.findOne({ id: req.params.id },{}, function(error, data){
     if(error){
       console.log("Error: " + error);
     }
     else {
       res.render('dataentry',{ title: 'Information for: ' + req.params.collection + ' ' + req.params.id +'.', data: data});
     }
   });

This should work fine. 这应该工作正常。 That being said, there is another way to make the rendering operation wait till the asynchronous function finishes execution. 话虽这么说,还有另一种方法可以使渲染操作等待异步函数完成执行。 That can be done using promises. 可以使用诺言来完成。

That can be done like: 可以这样完成:

var collection = db.collection(req.params.collection);
res.promise(collection.findOne({ id: req.params.id },{},function(error,data)).then(function(){
    res.render('dataentry',{ title: 'Information for: ' + req.params.collection + ' ' + req.params.id +'.', data: data});
});

I haven't checked my code, but hope this helps! 我尚未检查我的代码,但希望对您有所帮助!

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

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