首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具有角HttpClient和RxJS的嵌套RxJS

具有角HttpClient和RxJS的嵌套RxJS
EN

Stack Overflow用户
提问于 2018-11-08 12:59:04
回答 4查看 1.3K关注 0票数 0

因此,我有一个服务器,它可以根据请求返回对象数组。

示例:

代码语言:javascript
复制
[
  {
   id: 1
   name: name1
  },
  {
   id: 2
   name: name2
  }
]

数组可以有无限个元素;

之后,我必须用响应id为数组中的每个元素发送新的请求。

示例:

代码语言:javascript
复制
https://localhost/api/parent/${id}/child

答复:

代码语言:javascript
复制
[
  {
   childId: 1
   name: name1
  },
  {
   childId: 2
   name: name2
  },
  {
   childId: 3
   name: name3
  }
]

在此之后,我必须为新请求的每一个响应发送新的请求。

示例:

代码语言:javascript
复制
https://localhost/api/parent/${id}/child/${childId}/grandChild

答复:

代码语言:javascript
复制
[
  {
   grandChildId: 1
   name: name1
  },
  {
   grandChildId: 2
   name: name2
  },
  {
   grandChildId: 3
   name: name3
  }
]

和其他人的反应是相似的

在那之后,我必须组织数据,使其看起来像这样

代码语言:javascript
复制
[
  {
   id: 1
   name: name1
   children: [
            {
              childId: 1
              name: name1,
              grandChildren: [
                            {
                             grandChildId: 1
                             name: name1
                            },
                            {
                             grandChildId: 2
                             name: name2
                            },
                            {
                             grandChildId: 3
                             name: name3
                            }
                            ]
            },
            {
             childId: 2
             name: name2
            },
            {
            childId: 3
            name: name3
            }
        ]
  },
  {
   id: 2
   name: name2
  }
]

每个父类都有一个子数组,每个子元素都有一个grandChildren数组。

这是我的尝试,但如果我尝试在组件中执行parents.forEach(父=> console.log(parent.childern)),则没有定义

代码语言:javascript
复制
getData() {

return this.http.get<Parent[]>(baseUrl + 'parent', {withCredentials: true}).pipe(
      map(parents => {
        parents.forEach(parent => {
          this.getChildren(parent).subscribe(Children => {
            parent.Children = Children;
            parent.Children.forEach(Children => {
              this.getGrandChildren(Children).subscribe(grandChild => {
                Children.grandChildren = grandChild;
              });
            });
          });
        });
      return parents;
      })
        );

}

代码语言:javascript
复制
 getChildren(parent: Parent): Observable<Child[]> {
  return this.http.get<Children[]>(baseUrl + `parent/${parent.id}/children`, {withCredentials: true});

}

代码语言:javascript
复制
 getGrandChildren(child: Child): Observable<GrandChild[]> {
return this.http.get<GrandChild[]>(baseUrl + `children/${child.id}/GrandChildren`, {withCredentials: true});

}

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2018-11-08 21:23:03

考虑到您的问题,它似乎是递归性质的。

ParentChildGrandChild都类似于树的节点和叶子的平面表示形式。如果是这样的话,您可以查看,了解如何使用RxJS进行递归处理的一些细节。

严格按照你表达问题的方式,至少以我的理解,这里是解决问题的方法。

代码语言:javascript
复制
getParents()
.pipe(
  switchMap(parents => from(parents)),
  mergeMap(parent => getChildren(parent)
    .pipe(
      switchMap(children => from(children)),
      mergeMap(child => getGrandChildren(child)
        .pipe(
          tap(grandChildren => child.grandChildren = grandChildren),
          map(() => child)
        )
      ),
      toArray(),
      tap(children => parent.children = children),
      map(() => parent)
    ), 1  // cuncurrency set to 1 to guarantee same order
  ),
)
.subscribe(d => console.log(JSON.stringify(d, null, 2)))

我用下面的模拟数据和函数测试了它

代码语言:javascript
复制
const parents = [
  {id: 1, name: 'name1'},
  {id: 2, name: 'name2'},
];
const children = [
  {childId: 1, name: 'name1'},
  {childId: 2, name: 'name2'},
  {childId: 3, name: 'name3'},
];
const grandChildren = [
  {grandChildId: 1, name: 'name1'},
  {grandChildId: 2, name: 'name2'},
  {grandChildId: 3, name: 'name3'},
];

function getParents(): Observable<Parent[]> {
  return of(parents).pipe(delay(10));
}
function getChildren(parent: Parent): Observable<Child[]> {
  return (parent.id === 1 ? of(children) : of([])).pipe(
    delay(100)
  );
}
function getGrandChildren(child: Child): Observable<GrandChild[]> {
  return (child.childId === 1 ? of(grandChildren) : of([])).pipe(delay(1000));
}
票数 1
EN

Stack Overflow用户

发布于 2018-11-08 13:58:03

你可以这样做:

代码语言:javascript
复制
 getRoot() {
    return this.http.get<Parent[]>(baseUrl + 'parent', {withCredentials: true}).pipe(
      switchMap(items => forkJoin(items.map(i => this.getChild(i))))
    )
  }

  getChild(parent) {
    return this.http.get<Children[]>(baseUrl + `parent/${parent.id}/children`, {withCredentials: true}).pipe(
      switchMap(items => forkJoin(items.map(i => this.getGrandChild(i)))),
      map(resp => (parent.children = resp, parent))
    );

  }

  getGrandChild(parent) {
    return this.http.get<GrandChild[]>(baseUrl + `children/${child.id}/GrandChildren`, {withCredentials: true}).pipe(
      map(resp => (parent.grandChildren = resp, parent))
    )
  }

使用items.map将结果数组转换为相关子请求的数组。

然后,它使用forkJoin将所有这些请求连接到一个可观察的

然后使用switchMap发出请求,使用map将子级添加到响应中。

这里有一个Stackblitz演示

票数 1
EN

Stack Overflow用户

发布于 2018-11-08 13:17:42

你有可能混淆大写和小写吗?使用约定能够识别某物。

好吧,试试parent.children

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53208261

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档