我仍在努力更好地理解诺言。我从道格·史蒂文森(Doug Stevenson)的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
合并此信息,并返回mentorFirstName,mentorLastName,menteeFirstName,menteeLastName的数组。
但是,我因此而掉进了兔子洞。我决定将其缩减为工作代码,然后发布。
那么,我可以合并“ p”和“ p2”中的数据吗?还是我做错了方法?
我来自关系数据库背景,因此带有异步调用的Firestore集合/文档概念对我来说是一个新概念,我对此越来越熟悉(但还不够)。
我试图理解其中的各种示例,但是我认为我现在对承诺的不熟悉是一个主要障碍。 我已经尝试了漫游者和史蒂文·萨克的建议。 漫游者的建议不会出错,但我相信它正在放弃承诺。
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页面从不返回(始终显示为“正在思考”)。过去,这意味着云功能存在错误。云功能日志中没有错误,并且控制台功能日志中未显示数据(而在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);
});
});
我查看了这两个修改后的示例,觉得自己很了解,然后在没有得到结果时打sm自己。我觉得这两个都基于日志条目放弃了诺言,但是我不知道怎么做。在我看来,这些链接或链接在一起。那不是一个人。
答案 0 :(得分:0)
已移至答案,因为它太大了,无法发表评论:
我从来没有遇到过任何使用Promise.all
的示例(使用数据数组),但是也许这是来自诸如Bliebird
之类的较早Promise库的示例,但不适用不再。
这是一个简单的示例:
Promis.all([ Promise.resolve('one'), Promise.reject(new Error('example failure') ])
.then( ( values ) => {
//values[0] = data from promise 1; 'one'
//values[1] = data from promise 2
})
.catch( ( error ) => {
// note that an error from any promise provided will resolve this catch
})
编辑:
根据要求,将您的代码修改为使用Promise.all:
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];
return {
mentee,
mentor
};
})
.catch(error => {
// Handle the error
console.log(error);
//response.status(500).send(error);
});
});
另一个没有您的数据库逻辑的示例,我不太了解:
var response1 = { "foo": "bar" }
var response2 = { "biz": "baz" }
return Promise.resolve( [ response1, response2 ] )
.then(areaSnapshot => {
const promises = [];
areaSnapshot.forEach(doc => {
promises.push(Promise.resolve( doc ));
})
return Promise.all(promises);
//response.send(data);
})
.then(citySnapshots => {
let mentee = citySnapshots[0];
let mentor = citySnapshots[1];
return {
mentee,
mentor
};
})
.catch(error => {
// Handle the error
console.log(error);
//response.status(500).send(error);
});
答案 1 :(得分:0)
您的方法可以起作用,但由于包含promises
和p
的一个p2
数组的形成而使您的方法变得混乱。
据我所知,您希望将每个文档所需的数据捆绑到一个对象中。
有很多方法可以做到这一点。这是一个使用内部Promise.all()
来聚合每个[p,p2]
对诺言,然后形成所需对象的人。
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]) => {
// 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': mentee.data(), // ???
'mentor': mentor.data() // ???
};
});
);
}
})
return Promise.all(promises);
})
.catch(error => {
console.log(error);
//response.status(500).send(error);
});
});
所有假设.get()
是异步的并且.data()
是同步的
返回的promise的成功路径将传递一组{area,mentee,mentor}
个对象。
由于我不完全了解数据,可能不是100%正确。应该不难适应。
答案 2 :(得分:0)
这是最终的工作代码。感谢@ Roamer-1888和“ @Steven Stark”
最终的代码有点像是两者提供的解决方案之间的交叉。非常感谢您的帮助。
因此,我对诺言更加满意。希望我能与他们合作得更多一些,以使他们感到更舒适,并增加保留它的机会。
// lets call this Integer reference ABC101
Integer i = new Integer(5);
//j points to i so j has the reference ABC101
Integer j = i;
//creates a new Integer instance for j?
j++;
//I want j++ to edit and return ABC101
System.out.println(i); // 5 not 6