1

Following this course https://www.pluralsight.com/courses/angular-2-getting-started and github materials product.service in that course trying to avoid calling http.get() request every time I click the link. I think it is a big waste to load file every time instead of saving it as an object in memory.

Trying to replace this code:

    getProducts(): Observable<IProduct[]> {
    return this._http.get(this._productUrl)
        .map((response: Response) => <IProduct[]> response.json())
        .do(data => console.log('All: ' +  JSON.stringify(data)))
        .catch(this.handleError);
}

with this one:

    public _observable: Observable<IProduct[]>;

    getProducts(): Observable<IProduct[]> {
    console.log('_observable before: ' + (this._observable));
    if(this._observable===undefined){
        console.log('_observable inside 1: ' + (this._observable));
        this._observable=this._http.get(this._productUrl)
            .map((response: Response) => <IProduct[]> response.json())
            .do(data => console.log('All inside observable: ' +  JSON.stringify(data)))
            .catch(this.handleError);
        console.log('_observable inside 2: ' + (this._observable));
    }

    console.log('_observable after: ' + (this._observable));
    return this._observable;
}

this line should never be called if this._observable is underfined this._observable=this._http.get(this._productUrl)

BUT IT IS CALLED!!!!

In a chrome console:

_observable before: [object Object]
product.service.ts:25 _observable after: [object Object]
product.service.ts:20 All inside observable:...

Last line shouldn't appear!

Mark Rajcok
  • 362,217
  • 114
  • 495
  • 492
  • Is the ProductListComponent subscribing to the observable again? If so, it will execute it again. – DeborahK Jun 10 '16 at 18:55
  • 2
    Check out the solutions presented here: http://stackoverflow.com/questions/36271899/what-is-the-correct-way-to-share-the-result-of-an-angular-2-http-network-call-in – DeborahK Jun 10 '16 at 19:01
  • 1
    actually, you guided me to the right direction it is about caching and adding magic words publishReplay(1) and refCount http://www.syntaxsuccess.com/viewarticle/caching-with-rxjs-observables-in-angular-2.0 if you do post the answer i will mark it as an answer – avagrkjllkjfdser3 Jun 10 '16 at 20:06
  • @DeborahK Thank you for the great course! – avagrkjllkjfdser3 Jun 10 '16 at 20:10

3 Answers3

1

_observable before is an object in log. And "last line" comment is outside if-else. Why not try :

    if (!Object.keys(this._observable).length) {
   console.log('_observable inside 1: ' + (this._observable));
    this._observable=this._http.get(this._productUrl)
        .map((response: Response) => <IProduct[]> response.json())
        .do(data => console.log('All inside observable: ' +  JSON.stringify(data)))
        .catch(this.handleError);
        console.log('_observable inside 2: ' + (this._observable));
        return this._observable;
   } else {
        console.log('_observable after: ' + (this._observable));
        return this._observable;
   }
1

For your code

 getProducts(): Observable<IProduct[]> {
return this._http.get(this._productUrl)
    .map((response: Response) => <IProduct[]> response.json())
    .publishReplay(1)
     .refCount()
    .do(data => console.log('All: ' +  JSON.stringify(data)))
    .catch(this.handleError);
}

Now you dont need to think about those conditions. publishReplay, refCount will share the same state among all observers. So publishReplay will help you to cache data and refCount will help observer to be available.

pd farhad
  • 6,352
  • 2
  • 28
  • 47
1

To avoid file being loaded you need to include to lines of code inside if statements:

            .publishReplay(1)
            .refCount()

The full code goes here:

    getProducts(): Observable<IProduct[]> {
    console.log('_observable before: ' + (this._observable));
    if(this._observable===undefined){
        console.log('_observable inside 1: ' + (this._observable));
        this._observable=this._http.get(this._productUrl)
            .map((response: Response) => <IProduct[]> response.json())
            .publishReplay(1)
            .refCount()
            .do(data => console.log('All inside observable: ' +  JSON.stringify(data)))
            .catch(this.handleError);
        console.log('_observable inside 2: ' + (this._observable));
    }

    console.log('_observable after: ' + (this._observable));
    return this._observable;
}