0

Im currently getting the new updated user value this way:

 this.Service.user$.subscribe(data => {
      this.userData = data;
      this.userId = data._id;
    });

but the updateUser is only executed every 5 secs.

So before its loaded the userData and UserId is empty.

is there a way i can get the stored user data from whats already in the service, instead of waiting 5 secs to it beeing executed again?

something like:

 this.Service.user$().GET((data:any) => { // gets the value already stored

    });

How would i accomplish this?

Service code:

     user$: Observable<any>;


  constructor(private http: HttpClient, private router: Router) {
    this.user$ = this.userChangeSet.asObservable();
  }



  updateUser(object) {
    this.userChangeSet.next(object);
  }

Edit:

Also, how would i destory all subscribes on ngOnDestroy event?

maria
  • 207
  • 5
  • 22
  • 56

2 Answers2

1

Use BehaviorSubject for userChangeSet. It emits value immediately upon subscription. Example:

userChangeSet = new BehaviorSubject<any>(this.currentData);
1

What you can do in your service is internally use a BehaviourSubject to store the values but expose this as an Observable.

Here is a quote from the docs detailing what a BehaviourSubject is

One of the variants of Subjects is the BehaviorSubject, which has a notion of "the current value". It stores the latest value emitted to its consumers, and whenever a new Observer subscribes, it will immediately receive the "current value" from the BehaviorSubject

See here for more.

Service code:

private _user$ = new BehaviourSubject<any>(null); // initially null

constructor(private http: HttpClient, private router: Router) {
  this.userChangeSet.subscribe(val => this._user$.next(val))
}

get user$ () {
  return this._user$.asObservable();
}

Then you can use it like normal in your component.

this.service.user$.subscribe(v => {
  // do stuff here
})

Note that the first value that the component will get will be null since this is the inital value of the BehaviourSubject.

EDIT:

In the component

private _destroyed$ = new Subject();

public ngOnDestroy (): void {
    this._destroyed$.next();
    this._destroyed$.complete();
}

And then for the subscription

this.service.user$.pipe(
  takeUntil(this._destroyed$)
).subscribe(v => {
  // do stuff here
})

The way this works is that when the destroyed$ subject emits, the observables that have piped takeUntil(this._destroyed$) will unsubscribe from their respective sources.

  • How would i destroy the subscribe when leaving component? – maria Mar 18 '19 at 02:23
  • A good way is to use `takeUntil`. Check out **6) Clean up subscriptions** [here](https://medium.freecodecamp.org/best-practices-for-a-clean-and-performant-angular-application-288e7b39eb6f) –  Mar 18 '19 at 02:28
  • is there some kind of tslint i need to update? get an error: http://prntscr.com/n06edf – maria Mar 19 '19 at 20:38
  • ERROR in src/app/global.service.ts(18,33): error TS1005: ';' expected. – maria Mar 19 '19 at 20:39
  • My initialisation was incorrect, should be `private _user$ = new BehaviourSubject(null)`. Have updated the answer! –  Mar 20 '19 at 00:52
  • still getting: http://prntscr.com/n0e5xf you never mentioned how userChangeSet variable should be? currently its: private userChangeSet = new Subject(); – maria Mar 20 '19 at 09:36
  • That `.user.subscribe` should work. If `userChangeSet` is a subject you should be able to subscribe to it and call `.next()` as you detailed in your question. –  Mar 20 '19 at 19:58
  • i dont understand why it wont work with me properly... code: http://notes.io/5nTS – maria Mar 20 '19 at 20:11
  • Did you remember to add the `get user$ () { return this._user$.asObservable(); }` to the `GlobalService` –  Mar 20 '19 at 20:55
  • i edited to: user$ = this._user$.asObservable(); and then it seems to work . – maria Mar 20 '19 at 21:06
  • Good to hear its fixed :) –  Mar 20 '19 at 21:27