@kovalenko/http-request-cache
v1.2.4
Published
TS decorator for caching logic of API calls.
Downloads
272
Readme
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; // If `refCount` is true, the source will be unsubscribed from once the reference count drops to zero
windowTime?: number; // Maximum time length of the replay buffer in milliseconds
ttl?: number; // cache time to live before it will be refreshed. Unlike refreshOn: interval(1000), ttl will not refresh automatically
storage?: HttpCacheStorage; // if none specified, the default cache object will be used
refreshOn?: Observable<unknown> | Subject<unknown> | BehaviorSubject<unknown>; // refresh trigger
}
export interface HttpCacheStorage {
setItem(key: string, item: Observable<any>): void; // sets cache
getItem(key: string): Observable<any> | undefined; // gets cache
deleteItem(key: string): void; // deletes cache
}
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 // set refCount to true to unsubscribe cache
}))
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);
});
// outputs:
// 1 {...}
setTimeout(() => {
this.dataService.list().subscribe(g => {
console.log('2', g);
});
}, 1000);
// outputs:
// 2 {...}
setTimeout(() => {
this.dataService.list().subscribe(g => {
console.log('3', g);
});
}, 6000);
// outputs:
// 1 {...}
// 2 {...}
// 3 {...}
setTimeout(() => {
this.dataService.list().subscribe(g => {
console.log('4', g);
});
}, 8000);
// outputs:
// 4 {...}
}
}
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');
}
}