Home > Blockchain >  I want to access old value as well as current value from Behavior Subject
I want to access old value as well as current value from Behavior Subject

Time:01-12

I have a scenario where in one of the components sends a value via form and i need to pass it to another component, so I have used Behavior Subject via a shared service as I thought it will be the best way to achieve what I need.

service.ts private Type$ = new BehaviorSubject<any>(null); getType(): Observable<any> { return this.Type$.asObservable(); } emitType(type: any | null): void { this.emitType$.next(type); }

component.ts where i am emitting

  ``` save(){
    .......
    this.service.emitType(_data.Type!);
   }```

component.ts where i am using ngOninit(){ this.service.getType().subscribe((type: any)=>{ this.Type = type console.log('types', this.Type); }) }

I found out behavior subject takes in only the last value, so i used ReplaySubject, now on console.log I can see that multiple values are fetched over my screen but still at the end type has last value. I need different type values to do different stuff

CodePudding user response:

You can use pairwise() to emit the current and previous values as an array, so when you subscribe, you'll get both:

private Type$ = new Subject<any>();

getType(): Observable<any[]> { 
  return this.Type$.pipe(
    startWith(undefined),
    pairwise(),
    shareReplay(1),
  ); 
}

emitType(type: any | null): void { 
  this.Type$.next(type);
}

Since pairwise() will not emit until it receives 2 emissions, we use startWith to feed it an initial undefined value. To achieve the multicast and replay functionality that BehaviorSubject has, we can add shareReply(1).

Then, in your component:

ngOnInit() { 
  this.service.getType().subscribe(
    ([previous, current]) => { 
      this.Type = ...; 
      console.log('types', { previous, current}); 
    }
  ) 
}

Note, it's not beneficial to wrap observables in functions (unless you are passing arguments needed to define it). Observables are lazy and nothing will happen until it is subscribed. Instead of creating a getType() method and returning observable, you can simply define a property that is an observable:

private _Type$ = new Subject<any>();

public type$: Observable<any[]> = this._Type$.pipe(
  startWith(undefined),
  pairwise(),
  shareReplay(1),
); 

emitType(type: any | null): void { 
  this._Type$.next(type);
}

Then, in your component:

ngOnInit() { 
  this.service.type$.subscribe(
    ([previous, current]) => { 
      this.Type = ...; 
      console.log('types', { previous, current}); 
    }
  ) 
}

Here's a little StackBlitz you can play with.

  • Related