簡體   English   中英

在對對象進行操作時鏈接遞歸 RxJS observables

[英]Chaining recursive RxJS observables while operating on object

我的后端有兩個 graphql 查詢: familiyTreeQuery返回一個家譜作為帶有孩子的節點,它也可以有孩子等等,以及personPicturesQuery($name: string)返回給定人的照片。

我的目標是調用familyTreeQuery ,迭代樹,如果這個人叫做 Alice,那么我想為這個人調用personPicturesQuery並將信息添加到樹中的節點。 應該對樹中的所有 Alice 執行此操作。

我的問題是,獲取圖片的調用是異步發生的,因此在將信息添加到節點之前返回數據。 我沒有按照這個問題中的建議使用flatMap ,因為在迭代樹時正在調用獲取圖片,而我無法在familyTreeQuery的管道方法中調用它。

public getContext(): Observable<TreeNode> {
  return this.familyTreeQuery.watch().valueChanges.pipe(
    map(result => {
      const familyTree = result.data.familyTree;;
      this.addPicturesToAlice(familyTree);
      return familyTree;
      
    })
  )
}

private addPicturesToAlice(node: TreeNode) {
  if (node.name === 'Alice') {
    this.fetchPictures(node.id).subscribe(pictures => {
      node.pictures = pictures;
    })
  }
  if (node.children && node.children.length > 0) {
    for (const childNode of node.children) {
      this.addPicturesToAlice(childNode);
    }
  }
}

private this.fetchPictures(personId): Observable<Picture[]> {
  return this.personPicturesQuery.fetch({id: personId}).pipe(
    map(result => {
      return result.data.personPictures;
    })
  )
}

據我所知,我不應該在addPicturesToAlice方法中調用 subscribe ,但我是 Angular 和 RxJS 的新手,並沒有找到使這項工作的方法。

您可以通過創建一組 observable 並遞歸傳遞它來實現這一點,然后使用forkJoingetContext訂閱它,如下所示:

public getContext(): Observable<TreeNode> {
  return this.familyTreeQuery.watch().valueChanges.pipe(
    switchMap(({ data: { familyTree } }) => forkJoin(this.addPicturesToAlice(familyTree)))
  )
}

private addPicturesToAlice(node: TreeNode, observables: Observable<Picture[]>[] = []): Observable<Picture[]>[] {
  if (node.name === 'Alice') observables.push(
    this.fetchPictures(node.id).pipe(tap(pictures => node.pictures = pictures))
  )

  if (node.children?.length) {
    for (const childNode of node.children) {
      this.addPicturesToAlice(childNode, observables);
    }
  }

  return observables;
}

private fetchPictures(personId: number): Observable<Picture[]> {
  return this.personPicturesQuery
    .fetch({ id: personId })
    .pipe(map(result => result.data.personPictures))
}

希望它足夠清楚。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM