angular 5 - 另一个观察者内部的观察者循环 - 有效的方法

angular 5 - loop of observers inside an other observer - efficient way to do it

我有一个 'get' 调用 returns 包含用户 ID 和名称的用户列表。 调用成功后,我需要调用另一个rest,让每个用户带上他的照片。

目前我是这样做的-

组件-

users;
userPhotos = {};

constructor(private dashboardService: DashboardService) {
  this.dashboardService.bringUsers().subscribe((data) =>{
    this.users = data;
    this.users.forEach((user) => {
      this.dashboardService.getPicture(user.userID).subscribe((data) => {
        if (data){
          this.userPhotos[user.userID] = window.URL.createObjectURL(data);
        } else {
          this.userPhotos[user.userID] = '';
        }
      });
    });
  });
}

在我的html-

<ng-container *ngFor="let user of users">
  <div>
      {{user.displayName}}
  </div>

  <display-picture [image]="userPhotos[user.userID]"></display-picture>
</ng-container>

其中display-picture是一个只呈现图片的组件。

有没有使用 rxjs 的有效方法?

您可以使用 forkJoin() 将来自多个可观察对象的所有最终发射值合并在一起。 RxJS 6 支持使用 key/value 对的对象映射来定义哪些可观察对象,但您必须为旧版本使用数组。

this.dashboardService.bringUsers().pipe(
   switchMap(users => forkJoin(
       users.reduce((acc, user) => (acc[user.userId] = this.dashboardService.getPicture(user.userID), acc), {}
   ))),
).subscribe((users: {[userId: number]: any}) => {
   Object.entries(users).forEach(([userId, data]:[number,any]) => {
      this.userPhotos[user.userID] = data ? window.URL.createObjectURL(data) : '';
   });
});

from 迭代每个用户,mergeScan 可用于执行可观察对象。为清楚起见,我将其分为两个功能。也可以用mergeScan

控制并发数
    const getUserPic=users=>from(users).pipe(
        mergeScan((acc, curr:any) =>
            getPicture(curr.userID).pipe(map(photo => {
                acc[curr.userID] = photo
                return acc
            }))
          ,{})
        ) 

bringUsers().pipe(
    tap(users=>this.users=users),
    switchMap(users=> getUserPic(users)),
    last()
).subscribe(console.log)

https://stackblitz.com/edit/rxjs-1bt172