热和冷可观察量:是否有 'hot' 和 'cold' 运算符?

Hot and Cold observables: are there 'hot' and 'cold' operators?

我查看了以下 SO 问题: What are the Hot and Cold observables?

总结一下:

然而,我觉得热与冷仍然是一个混乱的根源。所以这是我的问题:

这不是您所有问题的答案(我想知道所有问题!)但是可以肯定的是,所有 fromEvent Observables 都是热门的。 Click 似乎不是因为它不是像 mousemove 这样的 "continous" 事件,但无论如何订阅源(addEventListeneron 调用)仅在创建 Observable 时完成一次。所以很热。您可以在运算符 here and there 的源代码中看到它 - 创建的可观察对象是 shared,无论事件名称或来源是什么。

values 在你的 codepen 中是懒惰的 - 在订阅之前什么都不会发生,此时它会运行并连接起来。因此,在您的示例中,尽管您订阅了同一个变量,但它正在创建两个不同的流;每个订阅电话一个。

您可以将 values 视为附加了 mapclick 的流生成器​​。

该地图末尾的

.share() 会产生我们预期的行为,因为它是隐式订阅。

您的总结和链接的问题都是正确的,我认为术语可能会让您感到困惑。我建议您将热和冷可观察量分别视为主动和被动可观察量。

也就是说,无论是否有人订阅,活动(热)可观察对象都会发出项目。再一次,典型的例子是,无论是否有人在听,按钮点击事件都会发生。这种区别很重要,因为例如,如果我单击一个按钮然后订阅按钮单击(按此顺序),我将看不到已经发生的按钮单击。

被动(冷)可观察对象将等到订阅者存在后才会发出项目。想象一个按钮,在有人监听事件之前你不能点击它——这将确保你总是看到每一个点击事件。

默认情况下所有 Rx observables 都是 "cold"(或被动)吗?不,例如 Rx.fromEvent(input, 'click') 是一个热的(或活跃的)可观察对象。

I also read that Rx.fromEvent(input, 'click') is a cold observable(?)

事实并非如此。

Are there Rx operators which turn a cold observable into a hot observable?

将热(主动)可观察对象转变为冷(被动)可观察对象的概念是:您需要记录在没有任何订阅时发生的事件,并(以各种方式)向订阅者提供这些项目将来一起。一种方法是使用 Subject。例如,您可以使用 ReplaySubject 来缓冲发出的项目并将它们重播给未来的订阅者。

您指定的两个运算符(publishshare)都在内部使用主题来提供该功能。

How does it work with Rx operator withLatestFrom? Let cold$ be a cold observable which has been subscribed to. Will something$.withLatestFrom(cold$,...) be a hot observable?

如果 something 是一个热可观察对象,那么是的。如果 something 是冷可观察对象,则否。回到事件示例,如果 something 是按钮点击事件流:

var clickWith3 = Rx.fromEvent(input, 'click')
    .withLatest(Rx.Observable.from([1, 2, 3]);

Or if I do foo$.withLatestFrom(cold$,...), bar$.withLatestFrom(cold$,...) and subscribe to foo and bar, will I always see the same values for both?

不总是。同样,如果 foobar 是点击不同的按钮,那么您会看到不同的值。同样,即使它们是相同的按钮,如果您的组合函数(withLatest 的第二个参数)对于相同的输入没有 return 相同的结果,那么您将不会看到相同的值(因为它会被调用两次,如下所述)。

I thought Rx.fromEvent creates cold observables but that is not the case, as mentioned in one of the answers. However, I am still baffled by this behaviour: codepen.io/anon/pen/NqQMJR?editors=101. Different subscriptions get different values from the same observable. Wasn't the click event shared?

我会向您指出 我有过关于相同行为的问题。这个答案会比我更好地解释它,但它的要点是源(点击事件)是 "shared",是的,但你对它的操作不是。如果您不仅要共享点击事件,还要共享其上的操作,则需要明确地这样做。

几个月后我会回到我原来的问题,同时想分享获得的知识。 我将使用以下代码作为解释支持(jsfiddle):

var ta_count = document.getElementById('ta_count');
var ta_result = document.getElementById('ta_result');
var threshold = 3;

function emits ( who, who_ ) {return function ( x ) {
  who.innerHTML = [who.innerHTML, who_ + " emits " + JSON.stringify(x)].join("\n");
};}

var messages$ = Rx.Observable.create(function (observer){
  var count= 0;
  setInterval(function(){
    observer.onNext(++count);
  }, 1000)
})
.do(emits(ta_count, 'count'))
.map(function(count){return count < threshold})
.do(emits(ta_result, 'result'))

messages$.subscribe(function(){});

如其中一个答案所述,定义一个可观察对象会导致一系列回调和参数注册。必须启动数据流,这是通过 subscribe 函数完成的。 之后可以找到详细流程(为了说明而简化)。

Observables 默认是冷的。订阅一个可观察对象将导致上游订阅链发生。最后一个订阅导致执行一个函数,该函数将处理一个源并将其数据发送给它的观察者。

该观察者依次向下一个观察者发送数据,从而产生下游数据流,直至接收器观察者。下面的简化图显示了两个订阅者订阅同一个可观察对象时的订阅和数据流。

可以通过使用主题或通过 multicast 运算符(及其派生词,请参阅下面的注释 3)来创建热可观察对象。

引擎盖下的 multicast 运算符使用一个主题和 returns 一个可连接的可观察对象。所有对运算符的订阅都将是对内部主题的订阅。当 connect 被调用时,内部 subject 订阅上游 observable,数据流向下游。 主题在内部操作订阅的观察者列表并将传入数据多播给所有订阅的观察者。

下图总结了情况。

归根结底,理解观察者模式导致的数据流和算子的实现更重要

例如,如果obs很热,那么hotOrCold = obs.op1是冷还是热?无论答案是什么:

  • 如果 obs.op1 没有订阅者,则不会有数据流经 op1。如果有 hot obs 的订阅者,这意味着 obs.op1 可能会丢失数据
  • 假设 op1 不是 multicast-like 运算符,订阅两次 hotOrCold 将订阅两次 op1,并且来自 obs 的每个值将两次流过 op1.

备注:

  1. 此信息应该对 Rxjs v4 有效。虽然第 5 版已经消失 经过相当大的改动,大部分内容仍然逐字适用。
  2. 未表示取消订阅、错误和完成流程,因为 它们不在问题的范围内。调度程序也不是 考虑在内。除其他事项外,它们会影响 数据流,但先验不是它的方向和内容。
  3. 根据用于多播的主题类型,有 不同的派生多播运算符:

Subject type | `Publish` Operator | `Share` operator ------------------ | --------------------------- | ----------------- Rx.Subject | Rx.Observable.publish | share Rx.BehaviorSubject | Rx.Observable.publishValue | shareValue Rx.AsyncSubject | Rx.Observable.publishLast | N/A Rx.ReplaySubject | Rx.Observable.replay | shareReplay

更新 :另请参阅 the following articles, here, and there) 关于 Ben Lesh 的主题。

有关主题的更多详细信息可以在另一个 SO 问题中找到: