AngularFire嵌套Firestore查询获取RxJS Observable及DocumentReference解析问题
问题根因
你的代码有两个核心问题导致流中断无输出:
collaborators和categories是可选字段,如果questDoc中这两个字段不存在(值为undefined),直接调用map方法会抛出异常,直接中断整个流,后续的pipe逻辑自然不会执行。- Firestore的
valueChanges()返回的是永不完结的热Observable,而forkJoin要求所有传入的Observable都**完成(complete)**才会发射合并后的值,你用的userService.doc$、categoryService.doc$如果也是基于valueChanges()实现的,forkJoin会一直等待不会触发输出。
修复后代码
doc$(docId: string): Observable<Quest> { return this.doc(docId).valueChanges() .pipe( mergeMap(questDoc => { // 单次查询取第一个值后主动完结流,满足forkJoin触发条件 const owner$ = this.userService.doc$(questDoc.owner.id).pipe(take(1)); // 可选字段判空,不存在直接返回空数组的Observable避免报错 const collaborators$ = questDoc.collaborators?.length ? forkJoin(questDoc.collaborators.map(userRef => this.userService.doc$(userRef.id).pipe(take(1)))) : of([]); const categories$ = questDoc.categories?.length ? forkJoin(questDoc.categories.map(categoryRef => this.categoryService.doc$(categoryRef.id).pipe(take(1)))) : of([]); return forkJoin({ owner: owner$, collaborators: collaborators$, categories: categories$ }).pipe( map(value => { // 用结构赋值生成新对象,避免修改原questDoc产生副作用 return { ...questDoc, qid: docId, owner: value.owner, collaborators: value.collaborators, categories: value.categories } as Quest; }) ) }) ); }
修改说明
- 给所有传入
forkJoin的Observable加了take(1),拿到第一次返回值后主动完结流,满足forkJoin的触发要求 - 对可选字段做了空值判断,字段不存在/为空时直接返回
of([]),避免调用map时报错 - 删除了中间不必要的
joined.subscribe(),避免重复订阅产生额外请求,RxJS流会在外部订阅时自动执行内部逻辑 - 把
Object.defineProperties改为解构赋值生成新对象,避免修改原对象产生不可预期的副作用 - 如果你的
doc$方法本身就是单次查询逻辑,也可以直接用Firestore的get()方法替代valueChanges(),get()返回的Observable拿到数据后会自动完结,不需要额外加take(1)
内容的提问来源于stack exchange,提问作者Kaeks
相关产品推荐
相关产品推荐

