【发布时间】:2019-03-06 20:07:40
【问题描述】:
我仍在努力更好地理解 Promise。我从 Doug Stevenson 的关于 Promise 的 YouTube 视频中的一些示例开始,然后对其进行了修改以使用我的收藏。此代码与使用区域和城市的示例最相似。
代码如下:
exports.getMatchesNew = functions.https.onCall((data, context) => {
console.log("In On Call", data);
return db.collection('matches').get()
.then(areaSnapshot => {
const promises = [];
areaSnapshot.forEach(doc => {
var area = doc.data();
// console.log("Area is ", area.mentees);
// console.log("area ID is ", area.id);
// Loop through each mentee for a mentor
for (const city in area.mentees)
{
// console.log("City is ", area.mentees[city]);
// User Information for current mentee
const p = db.collection('users').doc(area.mentees[city]).get();
//User Information for current mentor
const p2 = db.collection('users').doc(doc.id).get();
//console.log("Doc ",p);
// would like to combine this together, which will end up on one row
// mentor name, mentee name
promises.push(p, p2);
}
})
return Promise.all(promises);
//response.send(data);
})
.then(citySnapshots => {
const results = [];
citySnapshots.forEach(citySnap => {
const data = citySnap.data();
// this log entry is occuring once for each p and p2 from above.
// I tried an array reference like citySnap[0] for mentee info and citySnap[1] for mentor info, this did not work.
console.log("cSnap is: ", data);
results.push(data);
})
return Promise.all(results);
})
.catch(error => {
// Handle the error
console.log(error);
//response.status(500).send(error);
});
});
输出是我得到指导者的名字和姓氏,然后我得到指导者名字和姓氏的输出(在单独的行上)。
在 Firestore 中,matches 集合中的每个文档只是导师的 ID 和学员 ID 的数组。所有用户信息都存储在“用户”集合中。 因此,我尝试遍历每个匹配文档,并为每个导师/学员组合生成一行数据。
当 p 和/或 p2 不可用时,我仍然需要添加一些处理。
我对“p”和“p2”的初衷是:
返回 p 的名字和姓氏,将它们重命名为 menteeFirstName 和 menteeLastName
返回 p2 的名字和姓氏,将它们重命名为导师名字和导师姓氏
组合此信息并返回一组mentorFirstName、mentorLastName、menteeFirstName、menteeLastName。
但是,我用它陷入了困境。我决定将其缩减为工作代码,然后发布。
那么,我可以合并来自“p”和“p2”的数据吗?还是我做错了?
我来自关系数据库背景,因此带有异步调用的 Firestore 集合/文档概念对我来说是一个新概念,我越来越熟悉(但还不够)。
我试图理解那里的各种示例,但我认为我对 Promise 的不熟悉是目前的主要障碍。 我已经尝试过 Roamer 和 Steven Sark 的建议。 Roamer 的建议并没有出错,但我相信它正在放弃承诺。
exports.getMatchesNew = functions.https.onCall((data, context) => {
return db.collection('matches').get()
.then(areaSnapshot => {
const promises = [];
areaSnapshot.forEach(doc => {
var area = doc.data();
for (let city in area.mentees) {
const p = db.collection('users').doc(area.mentees[city]).get();
const p2 = db.collection('users').doc(doc.id).get();
promises.push(
Promise.all([p, p2]) // aggregate p and p2
.then(([mentee, mentor]) => {
var mentorInfo = mentor.data();
var menteeInfo = mentee.data();
console.log("Mentor: ", mentorInfo.lastName);
console.log("mentee: ", menteeInfo.lastName);
// return a plain object with all the required data for this iteration's doc
return {
// 'area': area, // for good measure
// 'city': city, // for good measure
'mentee': menteeInfo, // ???
'mentor': mentorInfo // ???
};
})
);
}
})
return Promise.all(promises);
})
.catch(error => {
console.log(error);
//response.status(500).send(error);
});
});
我在日志中看到了数据,但没有返回任何记录(或者我在 .vue 页面中错误地引用了它们
<template slot="mentorLastName" slot-scope="row">
{{row.item.mentor.lastName}}
</template>
<template slot="menteelastName" slot-scope="row">
{{row.item.mentee.lastName}}
</template>
这适用于结果包含这些相同对象的其他情况。
Steven Sark 的代码也可以根据日志文件运行,没有任何错误。不同之处在于 vue 页面永远不会返回(总是显示为 'thinking')。在过去,这意味着云功能存在错误。云功能日志中没有错误,并且数据未显示在控制台功能日志中(而在 Roamer 版本中)。所以我无法证明这是有效的。
exports.getMatchesNew = functions.https.onCall((data, context) => {
console.log("In On Call", data);
return db.collection('matches').get()
.then(areaSnapshot => {
const promises = [];
areaSnapshot.forEach(doc => {
var area = doc.data();
// console.log("Area is ", area.mentees);
// console.log("area ID is ", area.id);
// Loop through each mentee for a mentor
for (const city in area.mentees)
{
// console.log("City is ", area.mentees[city]);
// User Information for current mentee
const p = db.collection('users').doc(area.mentees[city]).get();
//User Information for current mentor
const p2 = db.collection('users').doc(doc.id).get();
//console.log("Doc ",p);
// would like to combine this together, which will end up on one row
// mentor name, mentee name
promises.push(p, p2);
}
})
return Promise.all(promises);
//response.send(data);
})
.then(citySnapshots => {
let mentee = citySnapshots[0];
let mentor = citySnapshots[1];
console.log("Mentor: ", mentor.lastName);
return {
mentee,
mentor
};
})
.catch(error => {
// Handle the error
console.log(error);
//response.status(500).send(error);
});
});
我看了这两个修改过的例子,感觉我理解了它,然后当我没有得到结果时我打了自己一巴掌。我觉得这两个都是基于日志条目的承诺,但我不明白如何。在我看来,这些是链接或连接的。没有一个是单独的。
【问题讨论】:
-
Promise.all需要一个数组或 Promises,而不是数据。见:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… -
这是我仍在努力解决的问题。我认为 .get() 是一个承诺,我将这些推到了 promise.all 中。也许我不理解你的评论史蒂文。你是说我在传递数据而我不应该传递数据?
-
@MikeRees,是什么让承诺传递的值/对象变成行?你能用硬编码数据编写一些简单的代码,成功地将行传递给你的模型吗?
标签: javascript promise google-cloud-firestore google-cloud-functions