【问题标题】:Shared pre-subscribed RxJS observables共享的预订阅 RxJS 可观察对象
【发布时间】:2018-07-28 19:34:31
【问题描述】:

我有一个可观察对象,我需要它像一个承诺一样行事,即链应该在创建时执行一次并导致热可观察对象。

这是一个例子:

console.log('0 ms');

var foo$ = new Observable(obs => obs.next(1))
.map(v => {
  console.log('map, ' + v);
  return v + 1;
})
.share();

foo$.subscribe(); // would like to skip this

setTimeout(() => {
  console.log('100 ms');
  foo$.subscribe(v => { console.log('subscribe, ' + v); });
});

它会产生理想的输出:

0 毫秒

地图 1

100 毫秒

订阅 2

observable 需要额外订阅subscribe(),我想避免这种情况。

但这不适用于已完成的可观察对象:

console.log('0 ms');

var bar$ = new Observable(1, 2)
.map(v => {
  console.log('map, ' + v);
  return v + 1;
})
.share();

bar$.subscribe(); // would like to skip this

setTimeout(() => {
  console.log('100 ms');
  bar$.subscribe(v => { console.log('subscribe, ' + v); });
});

期望的输出:

0 毫秒

地图 1

地图 2

100 毫秒

订阅 2

订阅 3

实际输出:

0 毫秒

地图,1

地图,2

100 毫秒

地图,1

订阅 2

地图,2

订阅 3

每次订阅都会重新执行可观察链。

Observable.of 和增量映射为例。 observable 和它的链都可能代价高昂,因此链应该只执行一次,类似于 promise。但我不能只切换到 promise,因为完成的 observable 中可以有多个值。

另一个问题是 Promise 容易受到 GC 的影响,不会导致内存泄漏。我不确定可观察订阅是否可以保证这一点。

如何使用操作员预先订阅 observable 以避免虚拟 subscribe()

如何预先订阅具有多个值的已完成 observable 并避免多链执行?

可以像 Promise 一样对此类 observable 进行垃圾回收吗?

有类似的已回答问题,但我相信它们并不能解决所有问题

【问题讨论】:

    标签: javascript rxjs rxjs5


    【解决方案1】:

    observable 需要使用额外的 subscribe() 进行订阅,我想避免这种情况。

    你不能。订阅是执行一个可观察的周期。这就像说你想调用一个函数myFunc,而不必写括号myFunc()

    有办法“隐藏”这样做,但它们会显着改变正在发生的事情。并且订阅仍然发生,它只是隐藏在运营商中(您仍然必须致电)。例如,您可能必须改为 connect

    如何使用操作符预先订阅 observable 以避免虚拟 subscribe()?

    一般来说,您希望多播您的 observable。有很多运算符可以实现这一点,从原始的multicastpublishshare 以及各种publish*share* 变体。它们都做的事情略有不同,所以使用哪一个取决于你想要做什么。

    可以像 Promise 一样对此类 observable 进行垃圾回收吗?

    如果您妥善管理您的订阅,GC 就没有问题。但您确实需要确保所有订阅都在不再需要时结束。


    我发现自己无法给出具体的答案来实现您发布的所需输出,因为这对我来说没有意义。由于您将发出的值 (1, 2) 映射到它们的后继值,因此生成的 observable 会发出 2 和 3。我不明白为什么订阅应该只发出 2,而不是 3。

    【讨论】:

    • 这就像说你想调用一个函数 myFunc 而不必编写括号 myFunc() - 这适用于 Promise。 所以使用哪一个取决于您想要做什么 - 这是问题中描述的非常具体的行为。我主要关心的是完全可观察的。 只有 2 个,但不是 3 个 - 抱歉,这是一个错字。当然,subscribe 3 也会在那里。
    • 没有操作员可以“立即”连接多播可观察对象,因此您需要自己致电connect。如果您可以在第一次订阅时执行 observable,您可以添加 refCount(例如,publishReplay + refCount)。老实说,我不太了解打电话给subscribe 的反感。
    • 也就是说,您可以编写一个函数,该函数接受一个可观察对象,使用 ReplaySubject 订阅它并返回该主题。这样您就可以获得“立即”订阅。
    • 订阅不是一个大问题,它只是看起来像一个黑客,我想知道是否有更好的解决方案(例如,我不能在类字段中将foo$ = ... 作为单行,因为没有空间subscribe() 声明)。谢谢,我将使用 ReplaySubject 进一步调查我的选项。
    • 常见的用例是在第一个订阅上执行 observable,因此是 refCount。您始终可以在构造函数中将该订阅作为“加载”过程进行,因此第一个真正的订阅者不必等待。但我建议查看具体示例来讨论最佳策略。
    猜你喜欢
    • 2018-04-29
    • 1970-01-01
    • 2022-10-17
    • 2017-04-13
    • 2021-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-09
    相关资源
    最近更新 更多