By using Http, we call a method that does a network call and returns an http observable:
getCustomer() {
return
It's .publishReplay(1).refCount();
or .publishLast().refCount();
since Angular Http observables complete after request.
This simple class caches the result so you can subscribe to .value many times and makes only 1 request. You can also use .reload() to make new request and publish data.
You can use it like:
let res = new RestResource(() => this.http.get('inline.bundleo.js'));
res.status.subscribe((loading)=>{
console.log('STATUS=',loading);
});
res.value.subscribe((value) => {
console.log('VALUE=', value);
});
and the source:
export class RestResource {
static readonly LOADING: string = 'RestResource_Loading';
static readonly ERROR: string = 'RestResource_Error';
static readonly IDLE: string = 'RestResource_Idle';
public value: Observable<any>;
public status: Observable<string>;
private loadStatus: Observer<any>;
private reloader: Observable<any>;
private reloadTrigger: Observer<any>;
constructor(requestObservableFn: () => Observable<any>) {
this.status = Observable.create((o) => {
this.loadStatus = o;
});
this.reloader = Observable.create((o: Observer<any>) => {
this.reloadTrigger = o;
});
this.value = this.reloader.startWith(null).switchMap(() => {
if (this.loadStatus) {
this.loadStatus.next(RestResource.LOADING);
}
return requestObservableFn()
.map((res) => {
if (this.loadStatus) {
this.loadStatus.next(RestResource.IDLE);
}
return res;
}).catch((err)=>{
if (this.loadStatus) {
this.loadStatus.next(RestResource.ERROR);
}
return Observable.of(null);
});
}).publishReplay(1).refCount();
}
reload() {
this.reloadTrigger.next(null);
}
}
according to this article
It turns out we can easily add caching to the observable by adding publishReplay(1) and refCount.
so inside if statements just append
.publishReplay(1)
.refCount();
to .map(...)
I assume that @ngx-cache/core could be useful to maintain caching features for the http calls, especially if the HTTP call is made both on browser and server platforms.
Let's say we have the following method:
getCustomer() {
return this.http.get('/someUrl').map(res => res.json());
}
You can use the Cached
decorator of @ngx-cache/core to store the returned value from the method making the HTTP call at the cache storage
(the storage
can be configurable, please check the implementation at ng-seed/universal) - right on the first execution. The next times the method is invoked (no matter on browser or server platform), the value is retrieved from the cache storage
.
import { Cached } from '@ngx-cache/core';
...
@Cached('get-customer') // the cache key/identifier
getCustomer() {
return this.http.get('/someUrl').map(res => res.json());
}
There's also the possibility to use caching methods (has
, get
, set
) using the caching API.
anyclass.ts
...
import { CacheService } from '@ngx-cache/core';
@Injectable()
export class AnyClass {
constructor(private readonly cache: CacheService) {
// note that CacheService is injected into a private property of AnyClass
}
// will retrieve 'some string value'
getSomeStringValue(): string {
if (this.cache.has('some-string'))
return this.cache.get('some-string');
this.cache.set('some-string', 'some string value');
return 'some string value';
}
}
Here are the list of packages, both for client-side and server-side caching: