1

I have a component which is using url params.

On the ActivatedRoute.params change event, Http call is being sent to the server to get some details based on the ID param from the url.

The issue is in a case as following:

Once the url was changed to have new param, a new call was sent - this is OK.

then - the url was changed again so a newer call was now sent.

BUT - sometimes the old call response is coming AFTER the new one so the data is not correct and not matching latest URL.

What I actually need is a way to cancel the call once the url was changed.

I tried a solution based on this answer I found, with my below changes to match my case, but it doesn't seem to work.

app-routing.module.ts:

{ path: 'person-details/:id', component: PersonDetailsComponent }

person-details.component.ts:

protected ngUnsubscribe: Subject<void> = new Subject<void>();

ngOnInit(){
   this.activatedRouter.params
      .subscribe( (params) => {
           //here is what I tried to cancel prev calls
           this.ngUnsubscribe.next();
           this.ngUnsubscribe.complete();
           //the call
           this.personService.getPersonDetails(params['id'])
                //add call to ngUnsubscribe
               .pipe( takeUntil(this.ngUnsubscribe))
               .subscribe( (person) => {
                      //the old call response gets here after the new one so now
                      //this.person is not the latest one and not matching the id in the current url 
                      this.person = person;
                 });
      }

Note: ngOnDestroy is not being called if only the params in the url were changed, so doesn't match my case

What is the correct solution?

Community
  • 1
  • 1
Batsheva
  • 659
  • 4
  • 13
  • 27

1 Answers1

2

The correct solution is to use the switchMap RxJS operator:

this.activatedRoute.params.pipe(
  switchMap(params => this.personService.getPersonDetails(params['id']))
).subscribe(person => this.person = person);
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • Hi, thanks for your quick answer! I will try this now, but wanted to ask - it ther e a way to use this if I have some other code and a few calls in the ActivatedRoute.params change event? e.g. this.personService.getPersonDetails(params['id']) and this.personService.getPersonCars(params['id']) - how do I use it with your solution? – Batsheva Aug 15 '19 at 12:03
  • Assuming getPersonDetails() and getPersonCars() are two observables, you would use zip() or forkJoin() or combineLatest() or merge() to make a unique observable out of the two, and return that unique observable from the swicthMap callback. – JB Nizet Aug 15 '19 at 12:11
  • hey @Batsheva, did you manage to make it work with this solution? I'm kind of stuck on the same issue at the moment. – room_n Aug 02 '21 at 11:52