HttpRequestCache
TS decorator for caching logic of API calls.
Inspired by How to use TS decorators to add caching logic to API calls
Installation
npm install @kovalenko/http-request-cache
Supported API
@HttpRequestCache<T>((thisObj?: T, ...args: any[]) => HttpCacheOptions)
— A method decorator that will cache data
thisObj
is this object
args
are decorated method's arguments
interface HttpCacheOptions {
refCount?: boolean;
windowTime?: number;
ttl?: number;
storage?: HttpCacheStorage;
refreshOn?: Observable<unknown> | Subject<unknown> | BehaviorSubject<unknown>;
}
export interface HttpCacheStorage {
setItem(key: string, item: Observable<any>): void;
getItem(key: string): Observable<any> | undefined;
deleteItem(key: string): void;
}
Usage
Default cache storage
@Injectable()
export class DataService {
refresh$ = new Subject();
constructor(private http: HttpClient) { }
@HttpRequestCache<DataService>(dataService => ({
refreshOn: dataService.refresh$
}))
list(): Observable<any> {
return this.http.get('assets/angular.json');
}
}
Unsubscribe internal ReplaySubject when there are no subscribers
@Injectable()
export class DataService {
constructor(private http: HttpClient) { }
@HttpRequestCache<DataService>(dataService => ({
refCount: true
}))
list(): Observable<any> {
return this.http.get('assets/angular.json');
}
}
Custom cache storage
@Injectable()
export class DataService {
refresh$ = new Subject();
constructor(private http: HttpClient, private cacheService: CacheService) { }
@HttpRequestCache<DataService>(dataService => ({
storage: dataService.cacheService,
refreshOn: dataService.refresh$
}))
list(): Observable<any> {
return this.http.get('assets/angular.json');
}
}
Parametrized refresh
@Injectable()
export class DataService {
refresh$ = new Subject<string>();
constructor(private http: HttpClient) { }
@HttpRequestCache<DataService>((dataService, id: string) => ({
refreshOn: dataService.refresh$.pipe(filter(r => r === id))
}))
list(id: string): Observable<any> {
return this.http.get('assets/angular.json');
}
}
TTL
When someone subscribes list() method after TTL period, every subscription is being refreshed
@Injectable()
export class DataService {
constructor(private http: HttpClient) { }
@HttpRequestCache(() => ({
ttl: 5000
}))
list(): Observable<any> {
return this.http.get('assets/angular.json');
}
}
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent implements OnInit {
constructor(
private http: HttpClient,
private dataService: DataService
) { }
ngOnInit(): void {
this.dataService.list().subscribe(g => {
console.log('1', g);
});
setTimeout(() => {
this.dataService.list().subscribe(g => {
console.log('2', g);
});
}, 1000);
setTimeout(() => {
this.dataService.list().subscribe(g => {
console.log('3', g);
});
}, 6000);
setTimeout(() => {
this.dataService.list().subscribe(g => {
console.log('4', g);
});
}, 8000);
}
}
If cache invalidation is not necessary
@Injectable()
export class DataService {
constructor(private http: HttpClient) { }
@HttpRequestCache()
list(): Observable<any> {
return this.http.get('assets/angular.json');
}
}
License
MIT