i have a problem in making my caching more simpler. I think there is a better way to do this. My problem is that i have to do this "caching" codes in every get() function which is results in longer codes. Anyone help on how to do this the best way? Thanks. Here's my codes below. What i did in my codes is i do the get() function in my news.service.ts to get data from the http and i subscribe it in my news-list.
news.service.ts
getAllNews() {
if(this.newslist != null) {
return Observable.of(this.newslist);
}
else {
return this.httpClient
.get('http://sample.com/news')
.map((response => response))
.do(newslist => this.newslist = newslist)
.catch(e => {
if (e.status === 401) {
return Observable.throw('Unauthorized');
}
});
}
}
news-list.service.ts
this.subscription = this.newsService.getAllNews()
.subscribe(
(data:any) => {
console.log(data);
this.newslists = data.data.data;
},
error => {
this.authService.logout()
this.router.navigate(['signin']);
});
}
If you meant to have something generic, that you can use for different API calls or services, then you could do something like this:
import { Injectable } from '@angular/core';
import { HttpClient } from "@angular/common/http";
import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';
class CacheItem<T> {
url: string;
timestampCached: number;
data: T;
}
@Injectable({
providedIn: 'root'
})
export class MyCachedHttpClient {
cache: CacheItem<any>[] = [];
constructor(
private http: HttpClient,
) { }
get<T>(url: string, cacheTime?: number, forceRefresh: boolean = false)
: Observable<T> {
let cachedItem: CacheItem<T> = this.getCachedItem<T>(url);
if (cachedItem != undefined && !forceRefresh) {
let expireDate = cachedItem.timestampCached + cacheTime;
if (Date.now() < expireDate) {
return of(cachedItem.data);
}
}
return this.http.get<T>(url).pipe(
map(data => {
if (cacheTime) { // if we actually want to cache the result
if (cachedItem == undefined) {
cachedItem = new CacheItem();
cachedItem.url = url;
this.cache.push(cachedItem);
}
cachedItem.data = data;
cachedItem.timestampCached = Date.now();
}
return data;
})
);
}
private getCachedItem<T>(url: string): CacheItem<T> {
return this.cache.find(item => item.url == url);
}
}
And then just use MyCachedHttpClient
instead of HttpClient
everywhere.
Notes:
HttpClient
's get()
function since I didn't reimplemented the options
parameter here.