Home > Blockchain >  Angular/Typescript/RxJs: updating value of BehaviorSubject (Object Assign) while observing changes
Angular/Typescript/RxJs: updating value of BehaviorSubject (Object Assign) while observing changes

Time:11-22

I have a user object as BehaviourSubject which I observe. I would like to know if a particular value of my user has changed.

My code does not work, and I assume it's because of the way I assign a new object value to my user. I apparently overwrite both the old and new value of my BehaviorSubject, hence I would always compare the same object?

export interface User {
   id: string;
   username: string;
   isBanned: boolean;
   subscription?: UserSubscription;
}

export class AuthService {
  public readonly user$: Observable<User| undefined> = this.user.asObservable();
  user: BehaviorSubject<User| undefined> = new BehaviorSubject<User| undefined>(undefined);

  updateUserSubscription(newUserSubscription: UserSubscription): void {
    // Here I simply want to update the subscription-Object of my user
    this.user.next(Object.assign(this.user.value, newUserSubscription));
  }
}

export class MemberService {
  user?: User;
  private subscription?: Subscription;

  constructor(public auth: AuthService) {
     // Here I simply want to detect subscription changes
     this.subscription = this.auth.user$.pipe(
        pairwise(),
        filter(users => this.detectSubscriptionChange(users[0], users[1]))
     ).subscribe(([user1, user2] => { // some code ... })
   }

  detectSubscriptionChange(user1: User | undefined, user2: User | undefined): boolean {
      //subscription status is always the same, as the objects are always the same...
      return user1?.subscription?.status !== user2?.subscription?.status;
  }

}

Could you tell me how to properly assign new values to my current user object, so I can compare the values in the observable?

Thanks!

CodePudding user response:

If using Object.assign() to clone, you'd want to put make the "target" in the first parameter an empty object {}, then "assign" the user object to that new empty object, which represents the new user clone.

const user = Object.assign({}, this.user.value);

Currently you are merely "assigning" the subscription object to the current user.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

In latest JS / Typescript though, the spread operator is much nicer way to clone, and pretty much in line with how you were expecting Object.assign() to work for cloning:

const user = {...this.user.value});

Not sure how your User and UserSubscription models are set up, but if I'm understanding your intent correctly, I think you're going to also new to then directly update the subscription value:

user.subscription = newUserSubscription this.user.next(user);

  • Related