我正在网站内聊天。为了存储数据,我使用聊天,用户,消息集合。
我希望结果在包含以下内容的数组中:
[{
username (another one, not me)
last update
last message
}]
在聊天模型中,我只有chatid
和array of two members
,因此我需要遍历User集合以使用user name
来获得user id
。我想将所有名称保存在数组中(将来,我也想遍历消息以获取每个chatid
的最新消息)。问题是,当我返回chatsList时,它为空。我认为我需要某种方式来使用Promise
,但是我不确定它应该如何工作。
Chat.find({ members: userId })
.then(chats => {
let chatsList = [];
chats.forEach((chat, i) => {
let guestId = chat.members[1 - chat.members.indexOf(userId)];
User.findOne({ _id: guestId })
.then(guest => {
let chatObj = {};
name = guest.name;
chatsList.push(name);
console.log("chatsList", chatsList)
})
.catch(err => console.log("guest err =>", err))
})
return res.json(chatsList)
})
.catch(err => {
errors.books = "There are no chats for this user";
res.status(400).json(errors);
})
答案 0 :(得分:1)
实际上,Promise.all是您要寻找的:
Chat.find({ members: userId })
.then(chats => {
let userPromises = [];
chats.forEach((chat, i) => {
let guestId = chat.members[1 - chat.members.indexOf(userId)];
userPromises.push(User.findOne({ _id: guestId }));
});
return Promise.all(userPromises).then(guests => {
let chatsList = [];
guests.forEach(guest => {
chatsList.push(guest.name);
});
return res.json(chatsList);
});
});
});
尽管最好使用ID列表($in
查询)对DB进行一次调用。像这样:
Chat.find({ members: userId })
.then(chats => {
let ids = [];
chats.forEach((chat, i) => {
let guestId = chat.members[1 - chat.members.indexOf(userId)];
ids.push(guestId);
});
return User.find({_id: {$in: ids}}).then(guests => {
let chatsList = [];
guests.forEach(guest => {
chatsList.push(guest.name);
});
return res.json(chatsList);
});
});
});
您可能想另外验证每个id
是否都有对应的guest
。
答案 1 :(得分:0)
您可以尝试以下方法:
Chat.find({ members: userId }).then(chats => {
let guestHashMap = {};
chats.forEach(chat => {
let guestId = chat.members.filter(id => id != userId)[0];
// depending on if your ID is of type ObjectId('asdada')
// change it to guestHashMap[guestId.toString()] = true;
guestHashMap[guestId] = true;
})
return Promise.all(
// it is going to return unique guests
Object.keys(guestHashMap)
.map(guestId => {
// depending on if your ID is of type ObjectId('asdada')
// change it to User.findOne({ _id: guestHashMap[guestId] })
return User.findOne({ _id: guestId })
}))
})
.then(chats => {
console.log(chats.map(chat => chat.name))
res.json(chats.map(chat => chat.name))
})
.catch(err => {
errors.books = "There are no chats for this user";
res.status(400).json(errors);
})
答案 2 :(得分:0)
您遇到了并发问题。例如,运行chats.forEach
,在forEach
内部运行User.findOne().then
:return
语句在User.findOne()
兑现之前就已经执行了。这就是为什么您的列表为空。
使用async/await
可以使代码更具可读性和实用性:
async function getChatList() {
const chats = await Chat.find({members: userId});
const chatsList = [];
for (const chat of chats) {
let guestId = chat.members[1 - chat.members.indexOf(userId)];
const guest = await User.findOne({_id: guestId});
chatsList.push(guest.name);
}
return chatsList;
}
然后使用代码将聊天列表实际发送回用户:
try {
return res.json(await getChatList());
} catch (err) {
// handle errors;
}