0

我正在尝试改进扁平化并减少我的 Rxjs 代码中的链接。

我的服务getAllItems()的 REST 调用返回以下 Items[]:

[{
  id: 101,
  name: 'Car',
  owner: 1
},
{
  id: 102,
  name: 'Table',
  owner: 2
}]

我有另一个端点getOwnerInfo(id:number)它提供基于“所有者”ID的信息,我想要组合的信息,所以最终答案应该如下所示:

[{
  id: 101,
  name: 'Car',
  owner: {
    id: 1,
    username: 'Mikelinin',
    name: 'Mikel',
  },
},
{
  id: 102,
  name: 'Table',
  owner: {
    id: 2,
    username: 'Thominin',
    name: 'Thomas',
  },
}]

我当前的实现 .subscribe 一次调用getAllItems,然后在订阅正文中迭代每个订阅getOwnerInfo的元素。

我一直在查看其他扁平化示例,但基本上它们“破坏”了数组,并且他们从未将其重新组合在一起。我需要输出是一个数组。

我尝试使用from()concatMap()mergeMap()但似乎我无法正确组合这两个请求。

4

2 回答 2

0

下面将使用from将不同的所有者 ID 数组转换为所有者 ID 流。然后它将使用toArray将该流转换回一个数组,并将项目数组映射到具有各自所有者对象的项目数组。

this.getAllItems().pipe(
  switchMap(items => {
    const ownerIds = Array.from(new Set(items.map(x => x.owner)));
    return from(ownerIds).pipe(
      concatMap(x => this.getOwnerInfo(x))
      toArray(),
      map(owners => items.map(x => ({ ...x, owner: owners.find(y => y.id === x.owner) })))
    )
  })
)
于 2021-11-15T15:42:57.233 回答
0

将您的项目数组映射到一个可观察的数组中,每个可观察对象都会发出更新的项目。然后将 observables 数组连接在一起。

getAllItems().pipe(
  
  // turn item[] into observable<updatedItem>[]
  map(items => items.map(item => getOwnerInfo(item.id).pipe(
    map(owner => ({...item, owner}))
  ),

  // join observable<updatedItem>[] into updatedItem[]
  switchMap(itemCalls => forkJoin(itemCalls))

).subscribe(console.log);

或者您可以一步完成映射和加入:

getAllItems().pipe(

  // source item[], do stuff, emit updatedItem[]
  switchMap(items => forkJoin(
    items.map(item => getOwnerInfo(item.id).pipe(
      map(owner => ({...item, owner}))
    ))
  ))
  
).subscribe(console.log);
于 2021-11-15T16:32:00.343 回答