首页 > 解决方案 > 在Angular中异步加载带有主题的图像

问题描述

在我的网络应用程序中,用户可以以一种形式创建对象(其中一个字段是图像)并以另一种形式制作它们的集合(通过从列表中选择它们的数量)。第三个组件显示所有集合的列表。由于每个非集合对象都有自己的图像并且可以是多个集合的一部分,所以我偶然发现了一个问题。在我的集合列表中,我不想多次加载同一个图像。我想出了这样的事情:

export class SetListComponent implements OnInit {
    private sets: ObjectSet[];
    images: Map<number, ReplaySubject<string>>;

    constructor(){
        this.image = new Map();
        this.sets = [];
    }

    ngOnInit() {
        this.reloadSets();
    }

    reloadSets() {
        this.prizeService.getAllSets().subscribe(prizeSets => {
          this.updateImageMap(prizeSets);
          this.prizeSets = prizeSets;
        })
    }

  private updateImageMap(sets: ObjectSet[]): void {
    sets.map(set => set.elementsList)
      .reduce((acc, x) => acc.concat(x), [])
      .map(prize => prize.id)
      .forEach(objectId => {
        if (!this.images.has(objectId)) {
          this.images.set(objectId, new ReplaySubject(1));
          this.getImageFromAPI(objectId);
        }
      });
  }

  private getImageFromAPI(objectId: number) {
    const reader = new FileReader();
    reader.onload = (e) => {
      this.images.get(objectId).next(e.target['result']);
    };
    this.objectService.getImage(objectId)
      .subscribe(blob => {
        reader.readAsDataURL(blob);
      });
  }

  getObjectImage(objectId: number): Subject<string> {
    console.log('getObjectImage: '+objectId);
    return this.images.get(objectId);
  }

}

基本上在ngOnInit重新加载集中,即objectId添加<objectId, new ReplaySubject(1)>条目到地图,然后开始从 API 加载图像。有一个小的 HTML 示例:

<mat-expansion-panel *ngFor="let set of objectSets" class="m-2">
    <ng-container *ngFor="let obj of set.elementsList">
        <mat-list-item>
            <h4 mat-line>{{obj.name}}</h4>
            <p><img [src]="getObjectImage(obj.id) | async" alt="{{obj.id}}"/></p>
        </mat-list-item>
    </ng-container>
</mat-expansion-panel>

我决定使用 ReplaySubject 因为我读到它可以被多个订阅者使用,并且当新订阅者到来时它总是返回最后一个值(在这种情况下只有一个最后一个值)。我认为我的 HTML 将调用方法getObjectImage并订阅ReplaySubject. 因为console.log('getObjectImage: '+objectId);我发现这个方法被调用的次数比我列表中的对象要多。我的问题:

标签: angularimageasynchronoussubjectreplay

解决方案


推荐阅读