有个应用场景:首页文章显示,输出所有的文章,每篇文章除了本身的数据外还要带上该文章的作者名,保存文章的时候已经带有作者的id,现在的问题是输出所有文章的时候,首先读取出每篇文章的作者id,再根据这个作者id去用户表里找对应的作者名。但是最后只能得到一个用户的数据,为什么呢?纠结了好多天。。。
module.exports = function(req, res) { var blog = require(’…/models/blog’); var user = require(’…/models/user’);
blog.get(null, function(status, message) { message.forEach(function(m) { user.get({_id: m.author_id}, function(ustatus, umessage) { console.log(umessage); }); }); }); };
this has nothing to do with node. more like a javascript understanding problem. it’s because of the function scope and the nature of closure.
you should use async. https://github.com/caolan/async
能解释的清楚点吗,只能用同步来解决了?
javascript closure。 中文不知道叫什么。
var funcs = {}; for (var i = 0; i < 3; i++) { // let’s create 3 functions funcs[i] = function() { // and store them in funcs console.log("My value: " + i); // each should log its value. }; } for (var j = 0; j < 3; j++) { funcsj; // and now let’s run each one to see }
和下一个的区别。
var funcs = [];
function createfunc(i) { return function() { console.log("My value: " + i); }; }
for (var i = 0; i < 3; i++) { funcs[i] = createfunc(i); }
for (var j = 0; j < 3; j++) { funcsj; // and now let’s run each one to see }
我明白这些区别,但是解决不了我的问题呀。。。。
找到了一个变通的方案,把所有的文章查询出来,然后把所有的用户查询出来,在用户数据返回的回调方法中,遍历匹配id值。。。 module.exports = function(req, res) { var blog = require(’…/models/blog’); var user = require(’…/models/user’);
blog.get(null, function(status, message) { user.get(null, function(ustatus, umessage) { message.forEach(function(m) { umessage.forEach(function(um) { if (m.author_id == um._id) { m._author_name = um.name; } }); });
console.log(message); }); }); };
这样,每篇文章中就包含了作者名了,以后扩展用户的其他信息,比如头像,就很方便了。不用在每篇文章中 都预留用户名和用户头像之类的数据了,只要每篇文章中保留一个作者id,就可以通过这个接口拿到该用户的 所有数据了。。。。
no that’s not a good solution. if you have many users or many blogs, this solution will not scale. you cannot bring in all the blocks and all the users into the application. it will either crash the application OR it will take a long time.
why not first call the blog, get all the ids and put it in an array and then call user.get on the ids. instead of doing forEach and do the function call, just aggregate and make the array first.
why not first call the blog, get all the ids and put it in an array and then call user.get on the ids. 你这句话的意思跟我第一次发的代码没区别吧? 不过,第二种方案的性能确实差。。。
make the array and pass the array into user.getAll(array) instead of doing m.author_id
mongoose可以使用path关联查询,请搜
呵呵,我也刚开始看。觉得你代码应该没问题。不过要是真的有问题的话,可以试试用下面的代码
blog.get(null, function(status, message) { message.forEach(function(m) { var theID = {_id: m.author_id}; user.get(theID, function(ustatus, umessage) { console.log(umessage); })(theID); }); });
我觉得你还是先看下message.length是多少吧,先确定是不是大于1!然后在看看每个m.author_id是多少
你的写法是错误的。已经确定message.length>1
@hnliji1107 只是看上去像是closure的问题,可是看代码应该不涉及这个问题。在function里面用到外部变量才需要这么做。写的时候没注意,应该写在函数的{}外面,不过你都没有传入变量,所以也用不着考虑closure了吧。所以你再看看每个m.author_id是多少吧? 我也刚开始学这个,要是你解决了。顺便告诉一下我这个的出错原因吧,多谢。
我感觉这段代码没问题。
连的什么数据库,不是MongoDB吧?
是的
建议你写一个JS文件,旁人只要安装了MongoDB,执行这个文件就可以重现上述问题。
这可能有助于问题的解决。
是个好办法,等我弄好了,发上来。。