我是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});
});
我还没有检查我的代码,但希望这有助于!