【问题标题】:Observable: Skip second subscription if first one already running可观察:如果第一个订阅已经在运行,则跳过第二个订阅
【发布时间】:2018-05-25 19:37:02
【问题描述】:

我有一个简单的代码,可以返回缓存的公司或数据库中的公司。问题是我几乎同时从 2 个不同的地方订阅了这个 observable。这会触发对数据库的 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;
                });
        }
    }

提前非常感谢!

【问题讨论】:

  • 你明白了吗?

标签: typescript rxjs


【解决方案1】:

TL;DR - 你可能想要publishReplay(1).refCount()shareReplay(1)

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

然而,大多数时候人们只是在它之后使用refCount 操作符将其转换回普通的 Observable。 refCount 操作符将跟踪可连接的 observable 的订阅者。当订阅者计数从 0 变为 1 时,它将连接。当订阅者数量从 1 变为 0 时,它将断开连接。

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

为方便起见,RxJs 提供了一些别名。以下是“基本”等价物:

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 请求。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-05
    • 1970-01-01
    • 1970-01-01
    • 2016-06-26
    • 1970-01-01
    • 2017-04-23
    • 1970-01-01
    相关资源
    最近更新 更多