我正在使用Node.js和猫鼬来获取数据。 在发送结果之前,我想遍历数据并获取另一个猫鼬集合的一些其他信息。
我无法管理它,第一个猫鼬呼叫正在等待,其他诺言已经完成。 我以为我的Promise和.then调用混在一起...:S
我的代码:
exports.checkChats = (req, res, next) => {
console.log(req.userData.userId);
let modifiedChats = [];
let partner;
Messages.find({ $or: [{ "users.starter": req.userData.userId }, { "users.partner": req.userData.userId }] })
.then(chats => {
if (chats) {
console.log('Start');
const promises = chats.map(async chat => {
if (chat.users.starter.toString() === req.userData.userId.toString()) {
console.log('fetch partnerData for partner ' + chat.users.partner);
partner = chat.users.partner;
}
if (chat.users.partner.toString() === req.userData.userId.toString()) {
console.log('fetch partnerData for starter ' + chat.users.starter);
partner = chat.users.starter;
}
User.findById(partner).then(fetchedPartner => {
console.log('Partner fetched: ', fetchedPartner.userName);
modifiedChats.push({ id: chat._id, status: chat.status, lastMessage: chat.lastMessage, partnerName: fetchedPartner.userName, partnerImg: fetchedPartner.imagePath });
});
});
Promise.all(promises).then(() => {
console.log('End');
res.status(201).json({
message: 'Chats found',
chats: modifiedChats
});
});
}
}).catch(error => {
res.status(500).json({
message: 'Couldnt fetch chats!',
error: error
});
});
};
以及Terminallog:
Start
fetch partnerData for partner 5eb8502aad51b72012a2ccd1
fetch partnerData for partner 5eb84c93ad51b72012a2cc56
End
Partner fetched: Summer
Partner fetched: Pepe
谢谢你们。
答案 0 :(得分:1)
嗨,您的代码中的问题位于此处
const promises = chats.map(async chat => {
if (chat.users.starter.toString() === req.userData.userId.toString()) {
console.log('fetch partnerData for partner ' + chat.users.partner);
partner = chat.users.partner;
}
if (chat.users.partner.toString() === req.userData.userId.toString()) {
console.log('fetch partnerData for starter ' + chat.users.starter);
partner = chat.users.starter;
}
User.findById(partner).then(fetchedPartner => {
console.log('Partner fetched: ', fetchedPartner.userName);
modifiedChats.push({ id: chat._id, status: chat.status, lastMessage: chat.lastMessage, partnerName: fetchedPartner.userName, partnerImg: fetchedPartner.imagePath });
});
});
此循环的每次迭代都调用User.findById(partner)
,该返回的状态是诺言并且是异步的。该函数不知道它需要等待其结果。
告诉函数等待User.findById(partner)
完成的一种方法是添加return
。
return User.findById(partner).then(fetchedPartner => {
console.log('Partner fetched: ', fetchedPartner.userName);
modifiedChats.push({ id: chat._id, status: chat.status, lastMessage: chat.lastMessage, partnerName: fetchedPartner.userName, partnerImg: fetchedPartner.imagePath });
});
您还可以删除异步输入
const promises = chats.map(async chat => {
这毫无用处,因为您始终没有使用async/await
。
这也是使用async/await
重构代码的示例。
exports.checkChats = async (req, res, next) => { // by putting async here, you are enabling a function to use await
try {
console.log(req.userData.userId);
let partner;
const chats = await Messages.find({ $or: [{ "users.starter": req.userData.userId }, { "users.partner": req.userData.userId }] }); // by putting await before a function call the returns a promise, you will have the access to the value it will return by this syntax
console.log('Start');
const promises = chats.map(async chat => { // by putting async here, you are enabling a function to use await; This is also a function so you will need to put async here if you want to use await inside
if (chat.users.starter.toString() === req.userData.userId.toString()) {
console.log('fetch partnerData for partner ' + chat.users.partner);
partner = chat.users.partner;
}
if (chat.users.partner.toString() === req.userData.userId.toString()) {
console.log('fetch partnerData for starter ' + chat.users.starter);
partner = chat.users.starter;
}
const fetchedPartner = await User.findById(partner); // same here, I put await because its a promise
console.log('Partner fetched: ', fetchedPartner.userName);
return { id: chat._id, status: chat.status, lastMessage: chat.lastMessage, partnerName: fetchedPartner.userName, partnerImg: fetchedPartner.imagePath }; // I am just returning the values here. By the end of the .map() it will have created an array of promises that each resolves the values return here
});
const modifiedChats = await Promise.all(promises); // this will convert the array of promises to an array of the values that was resolve by each of the promises.
console.log('End');
res.status(201).json({
message: 'Chats found',
chats: modifiedChats
});
} catch (error) { // using try catch is the way for catching thrown errors / rejected promises
res.status(500).json({
message: 'Couldnt fetch chats!',
error: error
});
}
};