Reputation: 3
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
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