Reputation: 568
I am using angular 5 and rxjs. I am making 2 service calls, one dependent on others results. I am doing it using flatMap. I am also using takeUntil so that I can abort operation at any given point. My code looks like below:
this.myservice.api1(param1).pipe(takeUntil(this.destroyed$), finalize(() => {
//do something after both api calls are completed
},
flatMap((result1) => {
//do some operation and create object x(this.objx)
return this.myservice.api2(param1);
})
).subscribe((result2) => {
//do something based on result2 and this.objx
})
This code is executed in for loop and loop gets executed for 200 times. Therefore 400 network calls are made. I have a button on UI to abort this operation and this.destroyed$ observable gets executed when it is clicked. I can abort this way for any iteration where second API call is not made(api2). If only first API is getting called, that request gets cancelled. If api2 has been called, which takes 20-30 seconds to respond, it doesn't get cancelled. I want both API calls to be cancelled. Is it possible?
Upvotes: 4
Views: 1204
Reputation: 96889
You can just restructure your chain and put takeUntil
at the end.
this.myservice.api1(param1).pipe(
mergeMap((result1) => { // flatMap is just alias for `mergeMap` which is the recommended name you should use
//do some operation and create object x(this.objx)
return this.myservice.api2(param1);
}),
takeUntil(this.destroyed$),
finalize(() => {
//do something after both api calls are completed
},
).subscribe((result2) => {
//do something based on result2 and this.objx
});
The problem you had is in how mergeMap
works internally (this is on purpose). mergeMap
merges its source Observable and all inner Observables. So if you put takeUntil
before mergeMap
you're just completing the source Observable while all inner Observables are still active.
If you put it after mergeMap
it will make the observer to complete which triggers dispose handlers bottom-up order and when mergeMap
is unsubscribed it unsubscribes from its inner Observables.
This is the relevant line: https://github.com/ReactiveX/rxjs/blob/master/src/internal/operators/mergeMap.ts#L147
Also have a look at this article from one of RxJS Core Devs: https://ncjamieson.com/avoiding-takeuntil-leaks/
Upvotes: 5