BehaviorSubject problem

Hi guys,
i have a problem with BehaviorSubject of Rxjs

I am subscribing a event(BehaviorSubject ) when user clicked edit button
this will navigate user to edit profile page and after successful profile update, the edit page will pushed back to previous page(profile page) and profile information updated with latest update(doing a api call that fires automatically due to BehaviorSubject subcription).
Now problem is when a user doing update multiple time my ‘loadProfile()’ function firing much more time.
Here is the testing scenario bellow

update first time -> loadProfile() function firing 1 time
update end time -> loadProfile() function firing twice <–expected to fire one time
update third time -> loadProfile() function firing thrice <–expected to fire one time

Here is my code


// profile page
navToEditPfl() {
    this.service.profileUpdated().subscribe(res => {
      console.log('is updated: ', res);
      if (res === true) {
        this.loadPflData(this.user.UserDetails.id); // <--this function is firing multiple times on above testing scenerio 
      }
    });
    const navigationExtras: NavigationExtras = {
      queryParams: {
        user: JSON.stringify(this.user)
      }
    };
    this.router.navigate(['edit-profile'], navigationExtras);
  }

// edit profile page
updateProfile(){
   //after successful update doing this
   this.navCtrl.pop();
   this.commonService.isPflUpdated.next(true);
}

//in service
profileUpdated(): Observable<boolean> {
    return this.isPflUpdated.asObservable();
  }

I have tried with this.isPflUpdated.unsubscribe(); but in that time when i click edit button it showing error ‘object unsubscribed’

Please help
Thanks

As you have discovered, when you have a long-lived Observable like the one returned from profileUpdated, you are responsible for managing subscriptions to it. In practice, the safest way to do this is using ngOnInit / ngOnDestroy. I use ngneat/until-destroy for this, but there are a number of manual idioms that do the same thing.

So I would recommend getting the subscription out of navToEditPfl and into ngOnInit, and ensuring somehow that you tear it down in ngOnDestroy. Incidentally, asObservable is pretty much pointless. You can just return isPflUpdated out of profileUpdated.

Thank you so much @rapropos. it works

Hi @dipankar123, please could you post your solution?

I am really struggling with this as my BehaviourSubject also get’s called everytime I navigate back to the page. To my understand ngOnInit and ngOnDestroy don’t really work well with Ionic because they’re only fired once.

You shouldn’t care how many times they’re called. All you should assume about lifecycle events of any name or flavor is that they are called in specific order. You can be assured that ngOnInit won’t get called twice in a row without an intervening ngOnDestroy, and that is enough for the design outlined in my earlier post.

Correct, but my point was that if I do an API request to GET data, then when I come back to the page later with a different ID param, the ngOnInit won’t be called again.

I would suggest not using lifecycle events to manage data freshness. There are generally two common situations:

  • the app maintains some sort of overall “selected target” that can be changed in various ways, and this component always wants to reflect the current target.
  • some sort of ID is being passed directly to the component, typically via an @Input binding

In the first situation, I use this idiom. In the second, I use ngOnChanges to indicate when the component should ask whatever service handles this to exchange the ID for a business-layer object.