nodejs/mongodb代码中的异步问题

Asynchronous issue within nodejs/mongodb code

本文关键字:异步 问题 代码 mongodb nodejs      更新时间:2023-09-26

我是nodejs/express/mongodb/jade的新手,我已经尝试了一段时间,现在把一个简单的网站放在一起,以帮助促进更有效的方式回到过去的数据,并能够快速重用它。我确定最简单的方法是提供一个动态URL,并开始取得良好进展,然后遇到了一个障碍。

最终目标:我希望使用URL参数来确定返回哪些数据。在本地运行时,语法类似于localhost/:collection/:id。例如:localhost/lastyear/aug2001。因此,结果页将显示去年集合中_ID等于aug2001的数据。

为了实现这一点,我目前在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;

集合内文档的结构如下所示:

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

为了测试看到某种形式的数据,我的jade文件的数据条目看起来如下(我知道选项卡在jade中很重要,它可能看起来不正确,但我确保选项卡是正确的):

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

当导航到/lastyear/aug2001时,我所看到的只是页面加载"查找信息…",我不确定为了显示文档数据,我缺少了什么玉语法。我很感谢任何帮助/建议更有效的方法来达到我的最终结果。

编辑:真正的问题不在于JADE显示,而在于从db中提取数据时的异步db调用。

从这里我看到你有异步问题。

试试这样

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
      });  
   }); 
});

代码不检查


正如@Mykola Borysyuk所提到的,这似乎是一个异步回调问题。在您的代码中,collection.findOne({ id: req.params.id },{})是一个异步函数,因此您不知道何时执行它。当您从函数回调外部呈现页面时,在呈现调用发生之前,条目似乎没有被修改。

正如上面的答案所提到的,实现这一点的一种方法是创建一个回调函数,并从回调内部呈现页面。就像@Mykola展示的那样。为了清楚起见,我把它写在下面。

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});
     }
   });

这应该可以正常工作。话虽如此,还有另一种方法可以使呈现操作等到异步函数完成执行。这可以通过promise来实现。

可以这样做:

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});
});

我还没有检查我的代码,但希望这有助于!