Mukil Deepthi
Mukil Deepthi

Reputation: 6452

Angular with Akita and Rxjs having issue with foreach inside outer observable

I am new to Angular with Akita.

I have an application where the users are loaded and set in the store. all user have an initial imageUrl property set to eg: 'http://testxxxxxx' The component query the store for all users, and pipe to calls a method which loops through each person, make an api call to get 'blob' image response from api, and update the store with the person's imageUrl = 'blob:http:2fk2fjadkf' and the component set the <img src='imageUrl'.

But for some reason the method inside the outer observable is looping for many times. not sure why.

Here is my code:

Component:

peopleToShow$ = this.peopleFacade.peopleToShow$;

Component.html uses peopleToShow$ and the imageUrl property of each person. Right now it is not taking the updated blob url which is set in the this.loadImagesAsBlobs

Facade:

  peopleToShow$ = this.peopleQuery.peopleToShow$
  .pipe(
    tap((people) => this.loadImagesAsBlobs(people))
  );

private loadImagesAsBlobs(people: Person[]) {
    people.forEach((person) => {
      if (!person.isUrlChecked) {
        this.imageDataService
          .getAndStoreImageOnClient(person.imageUrl)
          .pipe(
            take(1),
            switchMap((safeUrl) => {
              this.updatePersonWithBlobImageUrl(person.id, safeUrl);

              return EMPTY;
            }),
            catchError(() => {
              this.updatePersonWithBlobImageUrl(person.id, null);

              return EMPTY;
            })
          )
          .subscribe();
      }
    });
  }

  private updatePersonWithBlobImageUrl(id: number, blobUrl: SafeUrl) {
    this.peopleStore.updatePersonWithBlobImageUrl(id, blobUrl as string);
  }

Thanks

Upvotes: 0

Views: 245

Answers (1)

JSmart523
JSmart523

Reputation: 2497

It's not within this code, but when I've had this problem, it was because I had multiple things listening to a single observable, which means it was all happening several times.

To fix, change

peopleToShow$ = this.peopleQuery.peopleToShow$
.pipe(
  tap((people) => this.loadImagesAsBlobs(people))
);

to

peopleToShow$ = this.peopleQuery.peopleToShow$
.pipe(
  tap((people) => this.loadImagesAsBlobs(people)),
  share()
);

or use shareReplay(1) instead, if you're worried about peopleToShow$ emitting before everything downstream is set up.

Upvotes: 1

Related Questions