Nxt3
Nxt3

Reputation: 2071

Subscription has an inner subscribe for each item

I have the following service:

public loadMatchAnalysis(clientId: string): void {
    this.logger.info(`Calling matchAnalysisService to get everything for the 'Match Analysis' page`);

    this.matchAnalysisService.getMatchAnalysis(clientId).subscribe(
      (matches: MatchAnalysis[]) => {
        matches.forEach(match => {
          forkJoin(
            this.matchAnalysisService.getMappings(clientId, match.id),
            this.matchAnalysisService.getCalculationMethods(clientId, match.id)
          ).subscribe(([mappings, calculations]) => {
            match.mappings = mappings.filter(m => m.id === match.id);
            match.children = calculations.filter(c => c.id === match.id);

            console.log('mappings', mappings);
            console.log('calculations', calculations);
            console.log('matches', matches);
          });
        });

        //THIS ONLY NEEDS TO BE CALLED ONCE
        new GetMatchAnalysisLoadedAction({ data: matches }).dispatch();
      },
      (error: HttpErrorResponse) => {
        new GetMatchAnalysisLoadedAction({ error: error }).dispatch();
      }
    );
  }

What I'm trying to accomplish:

I need to make an API call that will return a list of matches. Each match has an id that I need in order to make two new API calls. As you can see, I'm using forkJoin to perform the calls and when I get the data back, I'm modifying the matches with the data I need. Once all of that is complete, I need to make a call to GetMatchAnalysisLoadedAction() with all the data (matches).

The above code works for the most part except for only calling GetMatchAnalysisLoadedAction() once--and I understand why that occurs.

Is there some RXJS magic to do all of this nicely?

Upvotes: 2

Views: 191

Answers (1)

Nxt3
Nxt3

Reputation: 2071

I solved it like so:

  public loadMatchAnalysis(clientId: string): void {
    this.logger.info(`Calling matchAnalysisService to get everything for the 'Match Analysis' page`);

    this.matchAnalysisService
      .getMatchAnalysis(clientId)
      .pipe(
        switchMap(matches => {
          const mappings = matches.map(match => this.matchAnalysisService.getMappings(clientId, match.id));
          const calculations = matches.map(match =>
            this.matchAnalysisService.getCalculationMethods(clientId, match.id)
          );

          return forkJoin(of(matches), ...mappings, ...calculations);
        })
      )
      .subscribe(([matches, mappings, calculations]: [MatchAnalysis[], MatchAnalysisMapping[], Calculation[]]) => {
        matches.forEach(match => {
          match.mappings = mappings.filter(m => m.id === match.id);
          match.children = calculations.filter(c => c.id === match.id);
        });

        new GetMatchAnalysisLoadedAction({ data: matches }).dispatch();
      });
  }

Upvotes: 1

Related Questions