Search code examples
angularangular-promiseangular2-http

Reuse the object returned from HTTP response without making another API call in Angular 4


I am using promise to retrieve a User-Details object in a Angular 4 app using Typescript.

Now, I am using part of that object at two different places in my application using simple get request. Something like this :

private _firstName: String;
private _email: String;

  get userDetail(): Promise<any> {
  return this.http
  .get(this._userDetailsURL)
  .toPromise()
  .then((response) => {
    this._firstName = response.json().firstName;
    this._email = response.json().email;
  })
  .catch((err) => err);
  }

  get firstName(): String {
    return _firstName;
  }

  get email(): String {
    return _email;
  }

So, how do retrieve firstName and email using their getter functions after the promise is resolved ?

I understand that I can reuse the same get() request twice but I don't want to make an unnecessary api call. I want to retrieve these values multiple times and make a single API call.

Thanks


Solution

  • As of rxjs 5.4.0 you can use shareReplay (https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/sharereplay.md)

    You basically store the observable sequence and return it when components subscribe to it.

    // service.ts
    observable$ = this.http
        .get(this._userDetailsURL)
        .map(res => res.json())
        .shareReplay();
    
    getUserDetail(){
        return this.observable$
            .toPromise();
    }
    

    now when a component subscribes to this, it will share the same api request (regardless if calls happen simultaneously or happen later). Here is a working plnkr (https://plnkr.co/edit/drngeofZsXuG9LfJkFob?p=preview) look at the console logs to see shareReplay work.


    Taking this a step further, you can implement a way to clear the shareReplay. For example if a user logs out, you would want to clear the user data.

    // service.ts
    $observable;
    
    getUserDetail(){
        // if no observable sequence found, create sequence
        if(!this.observable$){
            this.observable$ = this.http
                .get(this._userDetailsURL)
                .map(res => res.json())
                .shareReplay();
        }
    
        return this.observable$
            .toPromise();
    }
    
    clearUserCache(){
        this.observable$ = null;
    }
    

    Now when a user logs out, you can call clearUserCache() and when something subscribes to getUserDetail(), another http request will be initiated.