RxJS 缓存并使用 shareReplay 刷新

Rav*_*erg 5 rxjs angular rxjs-pipeable-operators

我正在对从 API 检索的某些数据使用缓存,出于逻辑原因,存储的数据仅在有限的时间内有效,因此我正在使用以下内容:

someApiData$ = this.getData()
    .pipe(shareReplay(1, 3000))
Run Code Online (Sandbox Code Playgroud)

对我来说似乎很明显但对shareReplay操作符的创建者显然不是的是,如果数据不再缓存,则应该重新获取,或者至少我应该有另一个参数可以给我这个选项,就像是:

someApiData$ = this.getData()
    .pipe(shareReplay(1, 3000, shouldRefresh))
Run Code Online (Sandbox Code Playgroud)

相反,下一个订阅者将获得空值。所以,我正在寻找一个优雅的解决方案来解决这个问题。

Rav*_*erg 10

经过对这个线程上的答案和网络上的一些其他方法的一些尝试后,这就是我最终得到的结果。它具有以下能力:

  1. 缓存值
  2. 如果不再缓存数据,则自动刷新值
  3. 直接与Observable
  4. 如果需要,指定缓存生命周期的持续时间
  5. 整理我的服务并提供可重用的解决方案

我的缓存实用程序:

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$;
    }
}
Run Code Online (Sandbox Code Playgroud)

我的数据服务:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)