Geoffrey Migliacci
Geoffrey Migliacci

Reputation: 402

Array of Observables request a string?

Hi I'm still experimenting with RxJS & I'm trying for each Observables in an array to retreive the linked image of this Observable like so :

  1. I have my array of Observable Assignment
  2. Foreach Assignment get its "Logo" property (it's the Id of the image) & if it have one retreive its image as a string (dataUrl)
  3. Return all Assignments with its Image property as an array

So far I've done this :

public collectAssignements(): Observable<Observable<AssignementEntity>> {
    return this.assignementService.get('').pipe(
      map((assignments: AssignementEntity[]) => from(assignments.map((assignment) => new AssignementEntity(assignment))))
    );
  }

public assignements(): Observable<AssignementEntity[]> {
    return this.collectAssignements().pipe(
      mergeMap((assignment: Observable<AssignementEntity>) => {
        return assignment;
      }),
      map((assignment: AssignementEntity) => {
        return assignment;
      }),
      // here I'd like to use my function getPhoto on assignment.Platform.Logo if there is one (Logo is an Id)
      // then set the retreived string (dataUrl) to assignment.Platform.Image
      // but I can't figure out how to do that?
      toArray()
    )
  }

To get my Image from my assignment I have to pass the photo Id (here assignment.Platform.Logo) into getPhoto here that returns an Observable string:

public fileReader(blob: Blob): Observable<string> { // @todo inclure le FileReaderService readAsDataURL
    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, size: string = "min"): Observable<string> {
    return this.httpClient.get(`${this.environment.get('webServiceUrl')}/photos/${id}/${this.endpoint.slice(0, -1)}/${size}`, { responseType: "blob" as "json" }).pipe(
      mergeMap((blob: Blob) => this.fileReader(blob))
    );
  }

The get of assignmentService returns an Observable<Assignment[]> & the AssignmentEntity have a Platform (entity) with a Logo property (it's an Id with a string). Moreover, the Platform entity have an Image property (string) empty by default waiting to be populated with a dataUrl.

Upvotes: 0

Views: 149

Answers (1)

Geoffrey Migliacci
Geoffrey Migliacci

Reputation: 402

After struggling with the RxJS documentation I came up with this solution:

public assignements(): Observable<AssignementEntity[]> {
    return this.assignementService.get('').pipe(
      map((assignments: AssignementEntity[]) => from(assignments.map((assignment) => new AssignementEntity(assignment)))),
      mergeMap((assignment: Observable<AssignementEntity>) => {
        return assignment;
      }),
      map((assignment: AssignementEntity) => {
        return assignment;
      }),
      mergeMap((assignment: AssignementEntity) => { // forEach assignment if it has a Logo then make a request to get the image
        return assignment.Platform.Logo !== null ? this.platformService.getPhoto(assignment.PlatformId).pipe(
          map((image: string) => {
            assignment.Platform.Image = image;
            return assignment;
          })
        ) : of(assignment); // return the base assignment if no logo
      }),
      toArray(), // convert to an array
    );
  }

Upvotes: 1

Related Questions