Как кэшировать и делиться ответом Http get()?

Следуя этому курсу https://www.pluralsight.com/courses/angular-2-getting-started и материалы github product.service в этом курсе пытается избежать вызова запроса http.get() каждый раз, когда я нажимаю на ссылку. Я думаю, что каждый раз загружать файл вместо того, чтобы сохранять его как объект в памяти, - большая трата времени.

Пытаюсь заменить этот код:

    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);
}

с этим:

    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._observable подчеркнуто this._observable=this._http.get(this._productUrl)

НО ЭТО НАЗЫВАЕТ!!!!

В хромированной консоли:

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

Последняя строка не должна появляться!


person avagrkjllkjfdser3    schedule 10.06.2016    source источник
comment
Подписывается ли ProductListComponent на наблюдаемое снова? Если это так, он выполнит его снова.   -  person DeborahK    schedule 10.06.2016
comment
Ознакомьтесь с решениями, представленными здесь: stackoverflow.com/questions/36271899/   -  person DeborahK    schedule 10.06.2016
comment
на самом деле, вы направили меня в правильном направлении, это кеширование и добавление волшебных слов publishReplay(1) и refCount syntaxsuccess.com/viewarticle/, если вы опубликуете ответ, я отмечу его как ответ   -  person avagrkjllkjfdser3    schedule 10.06.2016
comment
@DeborahK Спасибо за отличный курс!   -  person avagrkjllkjfdser3    schedule 10.06.2016


Ответы (3)


_observable before — это объект в журнале. И комментарий «последняя строка» находится вне if-else. Почему бы не попробовать:

    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;
   }
person Neeraj Suthar    schedule 10.06.2016
comment
результаты такие же - person avagrkjllkjfdser3; 10.06.2016

Для вашего кода

 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);
}

Теперь вам не нужно думать об этих условиях. publishReplay, refCount будет иметь одно и то же состояние для всех наблюдателей. Таким образом, publishReplay поможет вам кэшировать данные, а refCount поможет наблюдателю быть доступным.

person pd farhad    schedule 10.06.2016
comment
Я надеялся, что @DeborahK опубликует этот уже готовый ответ, но вы были первым - person avagrkjllkjfdser3; 11.06.2016
comment
Без операторов if это не влияет - person avagrkjllkjfdser3; 11.06.2016

Чтобы избежать загрузки файла, вам нужно включить строки кода внутри операторов if:

            .publishReplay(1)
            .refCount()

Полный код идет здесь:

    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;
}
person avagrkjllkjfdser3    schedule 11.06.2016