dmitrdv
dmitrdv

Reputation: 71

Convert observable of array of observable into observable of array

I am trying to query database. Iterate over list of results and for each item execute one more request. At the end of rxjs construction I have Observable<Observable<Timesheet>[]>. But I need to have Observable<Timesheet[]>. How to do that?

this.caseService.getElapsedCases(date).pipe(
  map(elapsedCases => elapsedCases.map(elapsedCase => {
    return this.caseService.findOneById(elapsedCase.caseId).pipe(
      map(loadedCase => {
        const timesheet: Timesheet = {
          id: elapsedCase.id,
          start: elapsedCase.start,
          end: elapsedCase.end,
          case: loadedCase,
          isActive: false
        };

        return timesheet;
      })
    );
  }))
);

Upvotes: 0

Views: 226

Answers (2)

Wilgert
Wilgert

Reputation: 706

Use mergeMap + forkJoin! mergeMap combines the values emitted by multiple Observables into one Observable. forkJoin allows you to wait for the result of a list of Observables and combine the results of all those Observables as a list (comparable to Promise.all). See: https://rxmarbles.com/#mergeMap and https://rxmarbles.com/#forkJoin

Thanks to the answer of ritaj I learned it should be forkJoin. This works:

const loadElapsedCase: Observable<TimesheetEnt[]> = getElapsedCase().pipe(
  mergeMap(elapsedCases => 
    forkJoin(
      elapsedCases.map(elapsedCase => {
        return findOneById().pipe(
          map(loadedCase => {
            return {
              id: elapsedCase.id,
              title: elapsedCase.title,
              case: loadedCase
            };
          })
        );
      })
    )
  )
);

In the StackBlitz: https://stackblitz.com/edit/rxjs-zidltc?file=index.ts

Upvotes: 0

Roberto Zvjerković
Roberto Zvjerković

Reputation: 10137

You need to forkJoin separate requests and mergeMap to source:

const loadElapsedCase: Observable<TimesheetEnt[]> = getElapsedCase().pipe(
  mergeMap(elapsedCases => elapsedCases.map(elapsedCase => {
    return forkJoin(findOneById().pipe(
      map(loadedCase => {
        return {
          id: elapsedCase.id,
          title: elapsedCase.title,
          case: loadedCase
        };
      }))
    );
  }))
);

Upvotes: 1

Related Questions