Loop of subscribes inside a subscribe?

2020-02-07 10:18发布

问题:

I'm currently struggling with multiples/forEach subscribe inside a subscribe, I'm trying to retreive a list of objects then retreive their images thanks to their ID. Currently I've done this :

this.appTypeService.get().pipe(
  map((apps: AppTypeEntity[]) => {
    return apps.map((app) => new AppTypeEntity(app));
  })
).subscribe((apps: AppTypeEntity[]) => {
  apps.forEach((app: AppTypeEntity) => {
    if (app.Logo != null) {
      this.appTypeService.getPhoto(app.Id).subscribe((image: string) => {
        app.Image = image;
      });
    }
  });
  this.appTypeList = apps;
});

The thing is that, since it's not executing in order sometimes an object's image from the list will be empty. What I would like is to get all my images & then setting the this.appTypeList.

Here is my getPhoto just in case :

  public fileReader(blob: Blob): Observable<string> {
    return Observable.create((obs: Observer<string | ArrayBuffer>) => {
      const reader = new FileReader();

      reader.onerror = err => obs.error(err);
      reader.onabort = err => obs.error(err);
      reader.onload = () => obs.next(reader.result);
      reader.onloadend = () => obs.complete();

      return reader.readAsDataURL(blob);
    });
  }

  public getPhoto(id: string): Observable<string> {
    return this.httpClient.get(`${this.environment.get('webServiceUrl')}/photos/${id}/${this.endpoint.slice(0, -1)}/min`, { responseType: "blob" as "json" }).pipe(
      mergeMap((blob: Blob) => this.fileReader(blob))
    );
  }

I can't figure how to do that? I looked into forkJoin but I can't find out how to use it correctly in my case.

回答1:

Since you already understood the usage of forkJoin, you are sort of on the right direction.

RxJS's forkJoin() will for the Array.forEach() loop to be completed before returning all the observables. If you are familiar with the usage of Promises in JavaScript, it is actually similar to Promise.all.

const observablesList = [];

apps.forEach(app => {
  observablesList.push(this.appTypeService.getPhoto(app.Id));
})

forkJoin(observablesList).subscribe(response => {
  console.log(response);
  // handle the rest
});