Firestore删除数组成员后订阅Observable返回含undefined值数组问题
问题根因
- 代码逻辑存在缺陷:修改后的
map操作符在校验数组存在undefined的场景下,没有显式返回值,JavaScript函数默认返回undefined,是结果数组出现undefined项的直接原因。 - Firestore本身的机制触发:执行写操作时Firestore会优先更新本地缓存,触发一次临时snapshot更新,待服务端数据同步完成后才会触发第二次正确的更新,原逻辑未对第一次临时脏数据做过滤。
修复方案
首先优化数据转换逻辑,统一过滤数组无效值,同时过滤无效的返回项,修复代码漏洞,该方案可以完全移除你之前定义的hasUndefinedInArray工具函数,简化代码逻辑:
getAllMyFamilies() { return this.getFamiliesDoc().pipe( tap((familiesDoc) => console.log("This is families doc in getAllMyFamilies", familiesDoc)), switchMap((fdoc: FamiliesDoc) => { // 处理fdoc为空的边界情况 if (!fdoc?.families?.length) return of([]); let familyDataDocs = fdoc.families.map(f => { return this.afs.doc(`family/${f}`).snapshotChanges().pipe( map((doc: Action<DocumentSnapshot<FamilyInfoWithoutId>>) => { const data = doc.payload.data(); if (!data) return null; // 直接过滤数组中的undefined和null值,无需提前校验 return { familyId: doc.payload.id, moderatingGuardian: data.moderatingGuardian, guardians: data.guardians?.filter(item => item != null) || [], okToReadKids: data.okToReadKids?.filter(item => item != null) || [], familyName: data.familyName, kids: data.kids?.filter(item => item != null) || [], isSearchable: data.isSearchable } as FamilyInfo; }), // 过滤空值,仅有效FamilyInfo向下游传递,同时做类型缩小 filter((famInfo): famInfo is FamilyInfo => !!famInfo) ); }) return combineLatest(familyDataDocs); }), // 可选:添加防抖,过滤间隔小于100ms的连续更新,避免页面闪烁 // debounceTime(100), tap((families: FamilyInfo[]) => console.log("This is families in getAllMyFamilies AFTER WITH ALL FAM DATA", families)), ); }
如果需要彻底避免本地缓存临时更新的影响,可以在combineLatest后添加100ms左右的防抖处理,过滤掉连续的临时更新,仅保留最后一次正确的服务端同步结果。
内容的提问来源于stack exchange,提问作者Willem Ghijsen
相关产品推荐
相关产品推荐

