如何在需要2个API调用的Angular / rxjs中加载我的对象

时间:2018-10-08 15:49:39

标签: angular rxjs

我正在使用Angular 6。

我有以下课程:

export class MyItem{
  id: string;
  name: string;
  gizmo: Gizmo;
};

export class Gizmo{
  id: string;
  name: string;
  color: string;
};

我必须进行2次API调用。
1-获取MyItems的数组。
2-获取给定MyItem的Gizmo。

我已经尝试过了:

this.myItemService.get<MyItem[]>(
    new FindParameters({ name: name })
  ).pipe(tap(z => {
    z.forEach(function (item) {
      this.gizmoService.get(item.id)
        .subscribe(z => {
          item.gizmo = z;
        });
    });

  }))
  .subscribe(x => this.totalCount = x.length);

但是gizmoService似乎不在函数内部。 (如果我将其拔出,服务很好)

那么我该如何加载需要2个单独的API调用的对象?

2 个答案:

答案 0 :(得分:1)

这应该很简单,只是要注意这不会保留相同顺序的项目。

this.myItemService.get<MyItem[]>(...)
  .pipe(
    mergeAll(), // flatten the array into single emission
    mergeMap(item => this.gizmoService.get(item.id).pipe(
      map(gizmo => {
        item.gizmo = gizmo;
        return item;
      })
    )),
    toArray(), // turn all result into an array again
  )
  .subscribe(...)

答案 1 :(得分:0)

调用.subscribe().subscribe()是一种反模式,必须不惜一切代价避免。相反,您应该做的是将您的api调用合并为一个可观察的对象,并使用.subscribe()获得最终结果。

根据我的观察,这是应如何转换可观察值以将Gizmo数据转换为项目数据的方法:

this.myItemService.get<MyItem[]>(
    new FindParameters({ name: name })
).pipe(
    mergeMap((myItems: MyItem[]) => {
        const gizmoRequestArray: Observable<MyItem>[] = myItems.map(item => {
            return this.gizmoService.get(item.id).pipe(
                map(z => {
                    item.gizmo = z;
                    return item;
                })
            );
        });
        return combineLatest(gizmoRequestArray);
    })
)
.subscribe(x => this.totalCount = x.length);