【问题标题】:RxjS shareReplay : how to reset its value?RxjS shareReplay:如何重置其值?
【发布时间】:2019-01-24 14:01:36
【问题描述】:

我使用shareReplay 调用一次(如缓存)一个网络服务来检索一些信息:

为我服务:

getProfile(): Observable<Customer> {
    return this.callWS().pipe(shareReplay(1));
}

在多个组件中:

this.myService.getProfile().subscribe(customer => {
    console.log('customer informations has been retrieved from WS :', customer);
});

现在我想添加一个方法来强制刷新信息(仅绕过一次 shareReplay)。我尝试将我的 observable 存储在一个变量中,并在重新初始化之前将其设置为 null,但它似乎破坏了组件订阅..

有什么帮助吗?

谢谢

【问题讨论】:

标签: typescript asynchronous caching rxjs reactive-programming


【解决方案1】:

我知道这个线程是旧的,但我想我知道另一个答案意味着预先设置一个“重置”主题以推送新值。检查这个例子:

private _refreshProfile$ = new BehaviorSubject<void>(undefined);

public profile$: Observable<Customer> = _refreshProfile$
  .pipe(
    switchMapTo(this.callWS()),
    shareReplay(1),
   );

public refreshProfile() {
  this._refreshProfile$.next();
}

在上面的 sn-p 中,所有profile$ 新订阅者都将收到最新发出的值(调用一次callWS())。如果您希望“刷新”正在共享的客户,您可以调用“refreshProfile()”。这将通过switchMapTo 发出一个新值,重新分配重播值并通知任何profile$ 开放订阅者。

祝你愉快

【讨论】:

    【解决方案2】:

    其他答案都很好,但不必重置实际的 shareReplayed observable,一种更简单的方法可能只是像这样缓存结果:

    protected profile$: Observable<Customer>;
    
    getProfile$(): Observable<Customer> {
      if (!this.profile$) {
        this.profile$ = this.callWS().pipe(shareReplay(1));
      }
    
      return this.profile$;
    }
    
    resetProfile() {
      this.profile$ = null;
    }
    

    参考:https://blog.angularindepth.com/fastest-way-to-cache-for-lazy-developers-angular-with-rxjs-444a198ed6a6

    【讨论】:

    • 不会为现有订阅者设置this.profile = null; 停止更新?
    • @xcvbn 现有订阅者在这种情况下只能获得一次发射,所以这不是问题-
    • 性能影响可能可以忽略不计,但请注意,如果视图中涉及getProfile,它会在每个更改检测周期运行。您基本上将“复杂性”从重置移动到检索,这在大多数情况下可能没问题 - 但根据上下文,这可能是相关的。
    • 通常我认为 getProfile$ 不会直接从视图中调用,您会将 profile$ = getProfile$() 作为类属性,然后将 profile$ 更新为新的 getProfile$ if你需要刷新
    【解决方案3】:

    听起来您可以预先添加一个主题,该主题将使用merge 注入新值:

    private refresh$ = new Subject();
    
    refreshProfile(...): void {
      this.refresh$.next(/* whatever */);
    }
    
    getProfile(): Observable<Customer> {
      return this.callWS().pipe(
        merge(this.refresh$),
        shareReplay(1),
      );
    }
    

    【讨论】:

    • 不知道它是如何工作的,但它确实有效。我遇到了同样的问题。
    猜你喜欢
    • 2020-11-06
    • 2023-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多