How can I load my object in Angular/rxjs that requires 2 API calls

蹲街弑〆低调 提交于 2019-12-25 03:38:05

问题


I am using Angular 6.

I have the following classes:

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

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

I have to make 2 API calls.
1 - To get the array of MyItems.
2 - To get the gizmo of a given MyItem.

I've tried this:

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);

However the gizmoService appears to not be in scope inside the function. (If I pull it out the service is fine)

So how can I load my object that will require 2 separate API calls?


回答1:


Calling .subscribe() into a .subscribe() is an anti-pattern and must be avoided at all cost. What you should do instead is merge your api calls into one single observable and get the end result with a .subscribe().

From what I see, here's how you should transform your observable to get your gizmo data into your item data:

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);



回答2:


This should be pretty straight forward, just be aware that this doesn't preserve the same order of items.

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(...)


来源:https://stackoverflow.com/questions/52705919/how-can-i-load-my-object-in-angular-rxjs-that-requires-2-api-calls

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!