【问题标题】:Angular – shareReplay not caching dataAngular – shareReplay 不缓存数据
【发布时间】:2021-06-29 03:25:28
【问题描述】:

我有一个 Angular 服务,它应该从后端获取一个大对象并无限期地缓存它。我不想要后续的 HTTP 调用。它看起来像这样:

@Injectable({
    providedIn: 'root'
})
export class SomeService {
    data$: Observable<MyData>;

    constructor(apiService: SomeApiService) {
        this.data$ = of(new MyData()).pipe(
            switchMap(c => apiService.get().pipe(shareReplay(1)))
        )
    }

    // used by a route resolver, which should execute the first (and ONLY) HTTP request:
    get dataLoaded$(): Observable<boolean> { 
        return this.data$.pipe(
            map(d => !!d)
        );
    }
}

认为这样做是:

  1. 从一个空的 MyData 对象开始,这样应用就不会在 HTTP 请求解析之前中断
  2. 切换到apiService.get() 发出后的结果,将其缓存并使用shareReplay(1) 将其转换为热Observable

相反,每次构造使用该服务的组件时,都会发送一个新的 HTTP 调用。

我做错了什么?

【问题讨论】:

    标签: angular caching rxjs


    【解决方案1】:

    shareReplay 不在正确的位置:

    你的版本:

    constructor(apiService: SomeApiService) {
        this.data$ = of(new MyData()).pipe(
            switchMap(c => apiService.get().pipe(shareReplay(1)))
        )
    }
    

    应该怎样

    constructor(apiService: SomeApiService) {
        this.data$ = of(new MyData()).pipe(
            switchMap(c => apiService.get()),
            shareReplay(1)
        )
    }
    

    这样做的原因是因为您共享的唯一内容是 apiService.get() 返回的 observable。因此,如果您有 2 个订阅者到 this.data$,它将创建整个流 2 次。

    如果您将 shareReplay 移动为整个流的最后一个运算符,则整个流是共享的,仅强制对其上方的所有内容进行 1 次订阅。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-21
      • 1970-01-01
      • 1970-01-01
      • 2018-03-27
      • 2017-08-06
      • 1970-01-01
      相关资源
      最近更新 更多