I am using a caching for some data retrieved from an API, for logical reasons the stored data is valid only for a limited time, so I am making use of something like:
someApiData$ = this.getData()
.pipe(shareReplay(1, 3000))
What seems to be obvious to me but apparently is not to the creator of the shareReplay
operator is that if the data is no longer cached it should be re-fetched, or at the very least I should have another parameter that will give me this option, something like:
someApiData$ = this.getData()
.pipe(shareReplay(1, 3000, shouldRefresh))
Instead, what the next subscriber will get is null. So, I am looking for an elegant solution to this issue.
After some trails with the answers on this thread and some other approaches on the web, this is what I ended up with. It gives the ability to:
Observable
My caching util:
export class SharedReplayRefresh {
private sharedReplay$: Observable<T>;
private subscriptionTime: number;
sharedReplayTimerRefresh(
source: Observable<T>, bufferSize: number = 1,
windowTime: number = 3000000, scheduler?: SchedulerLike): Observable<T> {
const currentTime = new Date().getTime();
if (!this.sharedReplay$ ||
currentTime - this.subscriptionTime > windowTime) {
this.sharedReplay$ = source.pipe(shareReplay(
bufferSize, windowTime, scheduler));
this.subscriptionTime = currentTime;
}
return this.sharedReplay$;
}
}
My data-service:
export class DataService {
constructor(private httpClient: HttpClient) { }
private dataSource =
new SharedReplayRefresh<Data>();
private source = this.httpClient.get<Data>(url);
get data$(): Observable<Data> {
return this.dataSource .sharedReplayTimerRefresh(this.source, 1, 1500);
}
}