在启动Web应用程序时,主要任务是检索存储在各个Firestore的集合和子集合中的所有用户信息。
问题在于,即使我使用诺言和加载状态来防止应用程序显示为空,也将使用所有集合数据(具有子集合的集合除外)来呈现应用程序。
- If user is logged
-- Set Loading Status Active
-- Load Collection A
-- Load Collection B and forEach, load all sub-collection
-- Load Collection C
-- Set Loading Status Inactive
这时,将渲染应用程序,但仅使用集合A和集合C渲染。集合B已加载(我可以通过Redux Logs看到),但无法在应用程序中看到。
仅当我更改组件状态(例如,打开/关闭菜单)时,这些数据才会出现。
这是我通过子集合检索集合的方法:
export function setCompanyJobs(user) {
return {
type: "SET_COMPANY_JOBS",
payload: loadCompanyJobs(user),
};
}
检索主集合的功能
export function loadCompanyJobs(user) {
return new Promise((resolve, reject) => {
let companyJobs = [];
db.collection("company").doc(user.selectedCompany).collection("jobs").get().then((jobs) => {
jobs.forEach((job) => {
loadJobLinkedServices(user, job).then((jobLinkedServices) => {
companyJobs.push({
id: job.id,
...
});
});
});
resolve(companyJobs);
}).catch(function (error) {
...
});
});
}
用于检索所有集合子集合的函数
export function loadJobLinkedServices(user, job){
return new Promise((resolve, reject) => {
let jobLinkedServices = [];
db.collection("company").doc(user.selectedCompany).collection("jobs").doc(job.id).collection("linkedServices").get().then((linkedServices) => {
linkedServices.forEach((linkedService) => {
jobLinkedServices.push({
id: linkedService.id,
...
});
});
resolve(jobLinkedServices)
}).catch(function (error) {
...
});
})
答案 0 :(得分:2)
完成时
return new Promise((resolve, reject) => {
let companyJobs = [];
db.collection("company").doc(user.selectedCompany).collection("jobs").get().then((jobs) => {
jobs.forEach((job) => {
loadJobLinkedServices(user, job).then((jobLinkedServices) => {
companyJobs.push({
id: job.id,
...
});
});
});
resolve(companyJobs);
}).catch(function (error) {
...
});
});
不能确保仅在jobs.forEach()
循环中触发的所有查询都完成后(即,对loadJobLinkedServices
函数的调用返回的承诺已解决),您的Promise才能解决。
我不知道reactjs,但是我认为您可以按照以下方式使用JavaScript Promise.all()
方法:
return new Promise((resolve, reject) => {
let promises = [];
let companyJobs = [];
db.collection("company").doc(user.selectedCompany).collection("jobs").get().then((jobs) => {
jobs.forEach((job) => {
promises.push(loadJobLinkedServices(user, job));
});
Promise.all(promises).
then(results => {
//Loop over the results array to populate the companyJobs array
resolve(companyJobs);
})
}).catch(function (error) {
...
});
});
此外,不要忘记将您的调用正确链接到不同的异步函数,例如:
query Collection A
THEN query Collection B
THEN query all sub-collections (with Promise.all())
THEN query Collection C
THEN set Loading Status Inactive
最后,最后一句话:请注意,get()
方法返回一个Promise,所以我不确定是否需要将对get()
方法的调用包装到一些新的Promises
中(再次,我并不精通reactjs,所以这个说法可能是错误的。)
换句话说,我认为您可以执行以下操作(例如用于loadJobLinkedServices
函数):
export function loadJobLinkedServices(user, job){
let jobLinkedServices = [];
return db.collection("company").doc(user.selectedCompany).collection("jobs").doc(job.id).collection("linkedServices").get()
.then((linkedServices) => {
linkedServices.forEach((linkedService) => {
jobLinkedServices.push({
id: linkedService.id,
...
});
});
return jobLinkedServices;
}).catch(function (error) {
...
});
})