JDuffy
JDuffy

Reputation: 3

Notify when Sequence of Observables Complete

I'm trying to use RxJS Observables to filter a list of objects based on a users selection. To get the list of filtered objects, I need to call three separate services in sequence and pass in the values from the previous service to the subsequent service.

NOTE 1: Each of these three services return Observable

NOTE 2: Each service can return an arbitrary number of results, which each need to get passed to the next service.

Only after the third service has completed emitting all of its values can my code continue normally.

Here is what I have right now:

this.firstService.getFirstResults(filterOption)
            .subscribe(firstResult => this.secondService.getSecondResults(firstResult)
                .subscribe(secondResult => this.thirdService.getThirdResults(secondResult)
                    .subscribe(thirdResult => this.processResult(thirdResult, firstResult),
                    null,
                    () => console.log("COMPLETE")))
            );

The above code works almost perfectly for me. In the end, the processResult() function correctly builds an Array with all the filtered objects.

However, I don't know how to get notified when the sequence of Observables has truly completed. I had hoped that the complete section of the third service would do the job, but it is printing to the console several times rather than just once.

NOTE 3: In the final call to processResult() I need to pass both the thirdResult value as well as the corresponding firstResult value returned from the firstService.getFirstResults().

Upvotes: 0

Views: 432

Answers (1)

t7yang
t7yang

Reputation: 754

switchMap provided second parameter to restructure the return value, below is the demo show how to do.

function getResult(filterOption) {
  return this.firstService.getFirstResult(filterOption).pipe(
    switchMap(
      firstResult => this.secondeService.getSecondResult(firstResult),
      ([firstResult, secondResult]) => ({ firstResult, secondResult }),
    ),
    switchMap(
      ({ secondResult }) => this.thirdService.getThirdResult(secondResult),
      ([{ firstResult }, thirdResult]) => ({ firstResult, thirdResult }),
    ),
  );
}

getResult(filterOption).subscribe({
  next: ({ firstResult, thirdResult }) => this.processResult(thirdResult, firstResult),
  completed: () => console.log('completed'),
});

Upvotes: 0

Related Questions