Search code examples
angulartypescriptrxjsobservablerxjs-observables

ConcatMap with a loop inside


I have this code. I need it to run sequentially. I am getting most of my data except two requests. They are being run in a loop since I need these two calls to run for each account. The requests run but they return observables. I need to get the data from them. Not sure how to do this...

this.subscriptions.push(
  this.service1
    .subscribeToHouseholdId()
    .pipe(
      concatMap((householdId: number) => {
        return forkJoin([this.service2.getAccounts(householdId), this.service3.getTemplates()]);
      }),
      concatMap(([accountResponse, templates]) => {
        return observableOf(
          accountResponse?.results.map((account) => {
            return forkJoin([
              this.service3.getData1(account.id),
              this.service3.getData2(account.id)
            ]);
          })
        ).pipe(
          map((data) => {
            return [data, accountResponse, templates];
          })
        );
      })
    )
    .subscribe(([data$, accountResponse, templatesResponse]) => {
      const accountResults = accountResponse as IAccount;
      const templates = templatesResponse as ITemplate;

      const templatesData = this.filterTemplatesData(templates);

      accountResults?.results.forEach((account, index) => {
        const { instruction, brokerage } = data$[index];
        const tableData = instruction as IInstruction[];
        const bepData = brokerage as IPlan;
      });
        
    });
);

When I get to the forEach at the bottom 'instruction' and 'brokerage' should have data but they are just observables. How can I get the data from those observables without nested subscriptions?


Solution

  • I am pretty sure that the crucial part here is the following code:

    return observableOf(
      accountResponse?.results.map((account) => {
        return forkJoin([
          this.service3.getData1(account.id),
          this.service3.getData2(account.id)
        ]);
       })
    

    The observableOf function (or of function) takes simple data (no observables) and emits them directly. You are mapping your 'results' array to observables (forkJoin returns an observable) which will be treated as simple data, e.g. the observables get emitted. You probably want to also use forkJoin instead of observableOf to subscribe to these observable and emit the result array once the complete:

    return forkJoin(
      accountResponse?.results.map((account) => {
        return forkJoin([
          this.service3.getData1(account.id),
          this.service3.getData2(account.id)
        ]);
       })