angular - 在 firestore 中删除数组的成员时,我遵循的 observable 将使用结果数组中的未定义值进行更新
问题描述
我有以下功能。第一个更新 firestore 数据库以从 db 对象的数组中删除一个值。
removeGuardianFromFamily(guardian: string, familyId: string) {
return this.afs.collection('family')
.doc(familyId)
.update({
guardians: firestore.FieldValue.arrayRemove(guardian)
}).then(() => { // Need to remove family from guardians family doc
return this.removeFamilyFromUsersFamDoc(guardian, familyId);
}).catch(() => {
return { success: false }
})
}
接下来的功能,获取family doc,获取所有family信息(我已经包含了抓取数据时使用的接口)。
export interface FamilyInfo {
familyId: string;
moderatingGuardian: string;
guardians: string[];
okToReadKids: string[];
familyName: string;
kids: string[];
isSearchable: boolean;
}
export interface FamilyInfoWithoutId {
moderatingGuardian: string;
guardians: string[];
okToReadKids: string[];
familyName: string;
kids: string[];
isSearchable: boolean;
}
getFamiliesDoc() {
return this.authservice.user$.pipe(
switchMap(user => {
if (user) {
return this.afs.collection('families')
.doc(user.uid)
.collection('myfamilies')
.doc('myFamiliesDoc')
.valueChanges();
} else {
return of(null);
}
}));
}
getAllMyFamilies() {
return this.getFamiliesDoc().pipe(
tap((familiesDoc) => console.log("This is families doc in getAllMyFamilies", familiesDoc)),
switchMap((fdoc: FamiliesDoc) => {
// here we fetch all family data
let familyDataDocs = fdoc.families.map(f => {
return this.afs.doc(`family/${f}`).snapshotChanges().pipe(
map((doc) => {
return { familyId: doc.payload.id, ...doc.payload.data() as FamilyInfoWithoutId } as FamilyInfo;
}));
})
return familyDataDocs.length ? combineLatest(familyDataDocs) : of([]);
}),
tap((families: FamilyInfo[]) => console.log("This is families in getAllMyFamilies AFTER WITH ALL FAM DATA", families)),);
}
我在 getAllMyFamilies() 中观察到问题。在第一次加载时,对象完美加载,并反映了数据库中的值。但是,当您停留在同一页面上时,如果数据库发生更改,例如调用 removeGuardianFromFamily(),就会出现问题。该对象最初说:</p>
familyName: "Day"
familyId: "famId"
guardians: Array [ undefined ]
isSearchable: true
kids: Array [ undefined ]
moderatingGuardian: "modGuard"
okToReadKids: Array [ undefined ]
但是 observable 然后重新触发,并且对象显示完整的数组并带有正确的信息,但是此时前端已经更新并且未定义的值是显示的值。
然后我想,我们如何检查未定义的值并仅在未定义时才显式设置它们。所以我做了以下事情:
hasUndefinedInArray(arr: string[]) {
let hasUndefined = false;
for (let mem of arr) {
if (mem === undefined) {
hasUndefined = true;
break;
}
}
return hasUndefined;
}
getAllMyFamilies() {
return this.getFamiliesDoc().pipe(
tap((familiesDoc) => console.log("This is families doc in getAllMyFamilies", familiesDoc)),
switchMap((fdoc: FamiliesDoc) => {
// here we fetch all family data
let familyDataDocs = fdoc.families.map(f => {
return this.afs.doc(`family/${f}`).snapshotChanges().pipe(
tap((doc) => console.log("This is doc.payload.data() in families in getAllMyFamilies IN THE MIDDLE *******************************************", doc.payload.data())),
map((doc: Action<DocumentSnapshot<FamilyInfoWithoutId>>) => {
if (!this.hasUndefinedInArray(doc.payload.data().guardians)
&& !this.hasUndefinedInArray(doc.payload.data().okToReadKids) && !this.hasUndefinedInArray(doc.payload.data().kids)) {
let guardArray = [];
let okToReadKidsArray = [];
let kidsArray = [];
for (let guard of doc.payload.data().guardians) {
if (guard !== undefined) {
guardArray.push(guard);
}
}
for (let ok of doc.payload.data().okToReadKids) {
if (ok !== undefined) {
okToReadKidsArray.push(ok);
}
}
for (let kid of doc.payload.data().kids) {
if (kid !== undefined) {
kidsArray.push(kid);
}
}
const famInfo: FamilyInfo = {
familyId: doc.payload.id,
moderatingGuardian: doc.payload.data().moderatingGuardian,
guardians: guardArray,
okToReadKids: okToReadKidsArray,
familyName: doc.payload.data().familyName,
kids: kidsArray,
isSearchable: doc.payload.data().isSearchable
}
return famInfo;
}
}),
tap((familyInfo) => console.log("This is familyInfo in families in getAllMyFamilies IN THE MIDDLE AFTER *******************************************", familyInfo)),);
})
return familyDataDocs.length ? combineLatest(familyDataDocs) : of([]);
}),
tap((families: FamilyInfo[]) => console.log("This is families in getAllMyFamilies AFTER WITH ALL FAM DATA", families)),);
}
这表明从 db 的初始拉取是成功的,并且没有数组具有来自以下行的未定义成员:
return this.afs.doc(`family/${f}`).snapshotChanges().pipe(
tap((doc) => console.log("This is doc.payload.data() in families in getAllMyFamilies IN THE MIDDLE *******************************************", doc.payload.data())),
但是,在此之后:
tap((familyInfo) => console.log("This is familyInfo in families in getAllMyFamilies IN THE MIDDLE AFTER *******************************************", familyInfo)),);
可以观察到,在初始更新时,FamilyInfo 对象中的每个数组都有一个未定义的值,如上所示。有什么策略可以解决这个问题吗?
解决方案
推荐阅读
- javascript - 未处理拒绝的承诺的意外 unhandledRejection 事件
- javascript - 如何将本地html文件放入网页
- google-sheets - 从另一张工作表的 A 列获取 B 列值
- c# - Slack 交互式请求未命中指定的 ASP.NET 控制器操作
- pandas - 如何在 Pandas 中调用自定义函数
- angular - 与嵌套的 observables 共享操作符
- typescript - 如何获取枚举值的索引?
- ios - 使用 Angular 登录 Apple 实施
- java - For循环打印数字模式不打印正确的模式
- google-apps-script - 如何找到我刚刚使用代码创建的 Google 工作表的 ID?