Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Http request made multiple times in Angular2 service

Tags:

http

angular

I have created a service that makes a simple GET request:

private accountObservable = null;

constructor(private _http: Http) {
}

getAccount () {
    // If we have account cached, use it instead
    if (this.accountObservable === null) {
        this.accountObservable = this._http.get('http://localhost/api/account')
            .map(res => <Account> res.json().data)
            .catch(this.handleError);
    }

    return this.accountObservable;
}

I have added that service in my bootstrap function to provide it globally (my hope is to provide the same instance to all components):

provide(AccountService, { useClass: AccountService })

The problem is when I call this service in different components, a GET request is made every time. So if I add it to 3 components, 3 GET requests will be made even though I check if an observable already exist.

ngOnInit() {
  this._accountService.getAccount().subscribe(
    account => this.account = account,
    error =>  this.errorMessage = <any>error
  );
}

How can I prevent the GET request to be made multiple times?

like image 982
Christoffer Avatar asked Feb 27 '16 18:02

Christoffer


2 Answers

Use Observable.share():

if (this.accountObservable === null) {
    this.accountObservable = this._http.get('./data/data.json')
      .share()
      .map(res => res.json())
      .catch(this.handleError);
}

Plunker

In the Plunker, AppComponent and Component2 both call getAccount().subscribe() twice.

With share(), the Chrome Developer tools Network tab shows one HTTP request for data.json. With share() commented out, there are 4 requests.

like image 96
Mark Rajcok Avatar answered Oct 12 '22 03:10

Mark Rajcok


There are two types of observables.

Cold Observable : each subscriber receive all the events ( from the begining )

Hot observable : each subscriber receive the events that are emited after subscription.

Cold Observables are the default one. That's what the WS calling is triggered many times.

To make an Observable Hot you have to use following Rx's operators chain :

.publish().refCount()

In your case :

getAccount () {

    let accountObservable = this._http.get('http://localhost/api/account')
            .map(res => <Account> res.json().data)
            .catch(this.handleError);

    return accountObservable.publish().refCount();
}
like image 2
Mourad Zouabi Avatar answered Oct 12 '22 02:10

Mourad Zouabi