Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BehaviorSubject variable keeps data after logout

Tags:

angular

rxjs

I have a shared service as follows:

data = new BehaviorSubject<any[]>([]);
constructor(userService: UserService){
  if (localStorage.getItem('data') === null) {
    userService.getAllData().subscribe(results =>

      this.data.next(results)
 }
  else {
    this.loadData()
  }
}

loadData() {
  let data = JSON.parse(localStorage.getItem('data');
  this.data.next(data);
}

setData(data) {
  localStorage.setItem('data', JSON.stringify(data))
  this.data.next(data)
}

And then on my component on ngOnInit() I have :

ngOnInit() {
  this.sharedService.data.subscribe(results =>
    this.allData = results;
  )
}

itemChange() {
  this.allData.slice(index, 5);
  this.sharedService.data.next(this.allData)
}

and OnLogout I have :

   localStorage.removeItem('data')

The issue is that on first page reload, the service gets called and I have the data as expected, I make changes and then after I logout, and log back in, on the storage I don't have the data key anymore, but yet the sharedService doesn't get called again, instead on the components onInit the this.sharedService.data is already populated from the last time.

How do I make it call the sharedService everytime so that it checks whether the item('data') is there or not, as it is on the service constructor ?

like image 403
JennyJ Avatar asked Jan 25 '26 10:01

JennyJ


2 Answers

I'd suggest you restructure your service then. Do it in this way.

You do not let Subscribers subscribe to the data-BehaviorSubject itself but to a getter-method instead that returns your object as an Observable. Same effect but you now have the possibility to call other private methods in addition whenever a subscription occurs.

import { Observable } from 'rxjs/Observable';

private data = new BehaviorSubject<any[]>([]);

constructor(private userService: UserService){}

getData(): Observable<Array<any>> {

    // called once with/by each subscription    
    this.updateData();

    return this.data.asObservable();
}

And you now call, with each new subscription, the private method updateData(). This method will do the check you currently do in your constructor. But this check will happen now not only once when the service gets instantiated but with each new run of your app whether you shut down the browser or simply log out.

getDataValue(): Array<any> {
    return this.data.getValue();
}

setData(val: Array<any>) {
    localStorage.setItem('data', JSON.stringify(val));
    this.data.next(val);
}


private updateData(): void {
       const storage = localStorage.getItem('data');

       if (storage === null) {

          this.userService.getAllData().subscribe(results => {
             this.data.next(results);
          }

      } else {
          this.data.next(JSON.parse(storage));
      }
}

And in your component:

import { Subscription } from 'rxjs/Rx';

private subscription: Subscription;

ngOnInit() {
   this. subscription = this.sharedService.getData().subscribe(results =>
      this.allData = results;
   )
}

ngOnDestroy() {
    if (this.subscription) {
        this.subscription.unsubscribe();
    }
}

This should do.

I guess you have to reset the value what you are emitting through behaviourSubject by emitting initial value. May be not the perfect answer but I believe it will work.

The reason behind this is custom observable will not complete itself, you need to do that manually.

like image 30
Hitesh Bariya Avatar answered Jan 27 '26 00:01

Hitesh Bariya