有幾種方法可以解決這個問題。主要的問題是,你假設在渲染模板時數據將被填充。情況並非總是如此,你可以並且應該總是假設你在做異步函數的時候,除非你等到每個函數調用完成,否則它不會被完成。
這是一種確保數據可用於渲染的天真方式。
Item.find().populate('list').exec(function (err, items) {
var len = items.length
, populatedItems = [];
items.forEach(function(item, i){
User.findById(item.list.user, function (err, user) {
item.list = item.list.toObject();
item.list.user = user;
populatedItems.push(item);
if (i + 1 === len) {
res.render('index', { items: items });
}
});
});
});
雖然這不是非常有效,並且不必要的數據庫調用。在我看來,這也很難推理。
Item.find().populate('list').exec(function (err, items) {
var itemMap = {}
items.forEach(function (item, i) {
// Map the position in the array to the user id
if (!itemMap[item.list.user]) {
itemMap[item.list.user] = [];
}
itemMap[item.list.user].push(i)
item.list = item.list.toObject()
});
// Can pull an array of user ids from the itemMap object
User.find({_id: {$in: Object.keys(itemMap)}}, function (err, users) {
users.forEach(function (user) {
itemMap[user._id].forEach(function(id) {
// Assign the user object to the appropriate item
items[id].list.user = user;
})
});
res.render('index', { items: items });
});
});
在與您就IRC進行進一步討論並進行故障排除後,以下是您的具體情況的工作示例。
Item.find().populate('list').exec(function (err, items) {
var itemIds = [];
items.forEach(function (item) {
itemIds.push(item.list.user)
});
// Can pull an array of user ids from the itemMap object
User.find({_id: {$in: itemIds}}, function (err, users) {
var userMap = {}
users.forEach(function (user) {
userMap[user._id] = user
});
res.render('index', { items: items, userMap: userMap });
});
});
感謝您的所有幫助,userMap顯得最爲理智。 – chovy