可观察:如果第一个已经运行,则跳过第二个订阅

时间:2018-05-24 19:51:51

标签: typescript rxjs

我有一个简单的代码,可以从DB返回缓存的公司或公司。问题是我几乎在同一时间从两个不同的地方订阅了这个观察点。这会触发对DB的2次调用,因此我希望仅在第一次完成时运行第二次订阅,并且已经存在缓存值。是否有一些通过rxjs运算符执行此操作的标准方法?

  public current(): Observable<Company> {
        if (this.cachedCompany) {
            return Observable.of(this.cachedCompany);
        } else {
            if (this.companyId == null) {
                return Observable.of(null);
            }
            return this.companyApiService.get(this.companyId)
                .map(x => {
                    this.cachedCompany = x;
                    return x;
                });
        }
    }

提前多多感谢!

1 个答案:

答案 0 :(得分:0)

TL; DR - 您可能需要publishReplay(1).refCount()shareReplay(1)

所以你需要两件事。第一个是防止重复订阅,第二个是缓存响应。要完成第一个操作,您可以使用multicast运算符。它将为源流创建单个内部订阅,并将结果共享给所有订阅者。现在,此运算符创建了一种名为ConnectableObservable的特殊类型的可观察对象,允许您在其上调用.connect()以使其变热。

但是,大多数情况下,人们只需使用refCount运算符将其转回正常的Observable。 refCount运算符将跟踪可连接可观察对象的订阅者。当用户数从0变为1时,它将连接。当用户数从1变为0时,它将断开连接。

multicast运算符将主题或主题工厂作为参数。它基本上订阅了源流,并将响应转发给您所有订阅者订阅的此主题。它的行为取决于你给它的主题。例如,如果您提供ReplaySubject(1),那么它将向新订户重播最后一个值。这就是你获得缓存的方式。

为方便起见,RxJs提供了一些别名。这是&#34;基本&#34;等对应:

publish() === multicast(new Subject())
publishReplay(#) === multicast(new ReplaySubject(#))
publishBehavior(value) === multicast(new BehaviorSubject(value))
share() === multicast(() => new Subject()).refCount()
shareReplay(#) === multicast(() => new ReplaySubject(#)).refCount()

最后一个(shareReplay)确实不准确,因为它在refCount从0变为1之后维持基础订阅的细微差别,并且当它从1变为0时不会释放它源流完成。这种细微差别在你的场景中可能并不重要,因为你正在做一个可能在响应时完成的http请求。

相关问题