DJC
DJC

Reputation: 1173

RxJS groupBy with NgRx selector never completes

Retrieving a list of fixtures from my API, I am attempting to group these fixtures by their date, which works when I call the service directly in my component, but not when I am selecting the fixtures from the store.

The following outputs 2 arrays - ie 2 groups of fixtures based on their date:

this.store.pipe(
  select(selectCurrentSeasonId)
).subscribe(seasonId =>  {
  this.fixtureService.getFixtures(seasonId).pipe(
    mergeMap(fixtures => fixtures),
    groupBy(fixture => fixture.matchDate),
    mergeMap(group => group.pipe(toArray())),
    tap(res => console.log(res))
  ).subscribe(fixtures => this.fixtures$ = fixtures);

However, when using a store selector for the fixtures rather than the service call, I get no output:

this.store.pipe(
  select(selectCurrentSeasonId)
).subscribe(seasonId =>  {
  this.store.dispatch(loadFixtures({seasonId}));
  this.store.pipe(
    select(selectAllFixtures),
    mergeMap(fixtures => fixtures),
    groupBy(fixture => fixture.matchDate),
    mergeMap(group => group.pipe(toArray())),
    tap(res => console.log(res))
  ).subscribe(fixtures => this.fixtures$ = fixtures);
});

If I move tap() to above the 2nd mergeMap() I get a GroupedObservable output in the console, but I can't iterate over it.

Upvotes: 2

Views: 686

Answers (1)

martin
martin

Reputation: 96959

The problem is that you're using toArray() that emits only when its source Observable completes on an Observable that never completes (this.store). Each group emitted by groupBy completes when the source Observable completes or when an optional durationSelector emits (https://rxjs.dev/api/operators/groupBy). Since ngrx store never completes then each individual groups never complete either by themselves.

It looks like you might want to use take(1) after select(selectAllFixtures) because then you're using mergeMap to unpack the array to separated emissions.

Upvotes: 1

Related Questions