使用node和express,我试图在响应呈现页面之前处理一些信息,但我没有运气这样做。有什么建议吗?
app.get("/Category", function (request, response) {
if (request.query.Id) {
// get all the posts by categoryId
ForumPost.find({categoryId: request.query.Id}, function (err, posts) {
if (err) throw err;
var usernames = {};
for (i = 0; i < posts.length; i++) {
User.findById(posts[i].userId, function (err, user) {
if (err) throw err;
var username = user.username;
usernames[i] = username;
});
}
response.render("Category", {
message: posts,
userList: usernames
});
});
}
});
答案 0 :(得分:0)
您实际上是在数据库中触发了很多查找。 User.findById是一个异步方法,并返回一个查询,该查询可以转换为一个promise,并最终完成。因此,当你点击
时,这些回调并没有被执行number
在呈现某些响应后,您的响应标头将在username变量上发送或不发送正确的值。 看看Promises/A+。
答案 1 :(得分:0)
您可能只想使用单个find
查询数据库,并将所有用户ID作为单个$in
过滤器传入,然后确保在回调处理程序中形成响应mongoose希望你作为第二个参数传入find
函数:
// build the list of all ids you need
var ids = posts.map(p => mongoose.Types.ObjectId(p.userId));
// let's remove duplicates, too
ids = ids.filter((id,pos) => ids.indexOf(id)===pos);
// find all these users in a single query:
User.find({
'_id': { $in: ids}
}, (err, users) => {
// handle the query result
if (err) {
// do something error related here
return ...
}
// no error: get the usernames and send the response
var usernames = users.map(user => user.username);
response.render("Category", {
message: posts,
userList: usernames
});
});
这使用现代箭头功能,但如果您使用旧版本的Node(pre-6),则可以使用经典功能签名轻松替换它们((a,b,...) => c
相当于function(a,b,...) { return c }
。从技术上讲,他们是(function(a,b,...) { return c; }).bind(this)
,但在上面的代码中并没有相关的区别。)