我有一个简单的代码,可以从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;
});
}
}
提前多多感谢!
答案 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请求。