Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Refresh/reload a Hot Observable sequence with RxJS

I am working on a Portal in Angular 2. On login I make a request to the server to fetch the logged-in user profile. The method to fetch user profile returns an observable which is subscribed at 6 different places when the application loads.

If I used a cold observable, this would result in 6 API calls to the server. So i switched to a hot observable by adding .publishLast().refCount().

This resulted in a single request sharing the data since user profile doesn't update on subsequent requests.

The problem starts here:

Now I have an Edit Profile functionality which updates the user profile via an HTTP PUT and as a result of that, I would like to expire the previously subscribed Observables and somehow trigger the sequence again so API is executed again and the subscriptions receive updated data.

Is there some way I could restart/re-trigger an already subscribed observable sequence?

Here is the code for the fetch user observable

fetch(){
    this.userObservable = Observable.fromPromise(this.getToken())
      .switchMap(token => {
        let headers = new Headers();
        headers.append('Authorization', `Bearer ${token}`);
        return this.http.get('/api/v1/admin/users/me?includes=role', {headers: headers})
      })
      .map((res: Response) => {
        let retVal: any = {
          data: new Deserializer({
            keyForAttribute: 'camelCase'
          }).deserialize(res.json())
        };
        this.user = retVal.data as MpUser;
        this.user.role = MpRoles[retVal.data.role[0].name];
        return this.user;
      })
      .publishLast()
      .refCount();
  }
like image 480
Mohammad Umair Khan Avatar asked Jan 10 '17 08:01

Mohammad Umair Khan


1 Answers

You can try to introduce subject to trigger fetch:

private fetchTrigger = new BehaviorSubject(null);

triggerFetch() {
  this.fetchTrigger.next();
}

fetch() {
  this.userObservable = Observable
    .combineLatest(
      Observable.fromPromise(this.getToken()),
      this.fetchTrigger
    )
    .switchMap(([token]) => {
      ...
    })
    ...
    .publishLast()
    .refCount();
}

Note that in this sample token is retrieved only once. If you need to get new token on each refresh:

private fetchTrigger = new BehaviorSubject(null);

triggerFetch() {
  this.fetchTrigger.next();
}

fetch() {
  this.userObservable = this.fetchTrigger
    .switchMap(() => Observable.fromPromise(this.getToken()))
    .switchMap(token => {
      ...
    })
    ...
    .publishLast()
    .refCount();
}
like image 177
Sergey Sokolov Avatar answered Sep 28 '22 03:09

Sergey Sokolov