什么是热和冷的可观察对象?

132

我观看了这个视频,并且我知道一般的原则 - 热的发生在没有订阅者时,冷的“按需”发生。此外,Publish()将冷转为热,而Defer()将热转为冷。

但是,我感觉我还缺少细节。以下是我想得到答案的一些问题:

  • 你能给出这些术语的全面定义吗?
  • 是否有必要在热可观察对象上调用Publish或在冷可观察对象上调用Defer?
  • 热/冷转换的方面有哪些 - 是否会丢失消息?
  • IObservable和IEnumerable的热和冷定义之间有什么区别?
  • 编写冷或热程序时应考虑哪些一般原则?
  • 关于热/冷可观察对象还有其他提示吗?

1
请参阅Rx中的IConnectableObservables - Richard Szalay
4个回答

206

来自: 安东·莫伊塞耶夫的书 “Angular Development with Typescript, Second Edition.” :

热和冷的Observable 有两种Observable: 热的和冷的。主要区别在于,冷的Observable为每个订阅者创建一个数据生成器,而热的Observable创建一个数据生成器,每个订阅者从同一生产者获取数据从订阅开始

我们来比较在Netflix上看电影和去电影院看电影。把自己想象成一个观察者。任何决定在Netflix上观看不可能的任务的人都会得到整部电影,无论他们什么时候按下播放按钮。Netflix为您创建一个新的流媒体生产者。这是一个冷的Observable。

如果您去电影院,演出时间是下午4点,制片人会在下午4点创建,然后开始流媒体。如果有些人(订阅者)迟到了,他们会错过电影的开头,只能从到达的那一刻开始观看。这是一个热的Observable。

冷的Observable在某些代码调用subscribe()函数时开始生成数据。例如,您的应用程序可以声明提供服务器上获取某些产品的URL的Observable。只有在订阅它时才会发出请求。如果另一个脚本向服务器发出同样的请求,它将得到相同的数据集。

热的Observable即使没有订阅者对数据感兴趣也会产生数据。例如,您的智能手机上的加速度计会产生有关设备位置的数据,即使没有应用程序订阅此数据。服务器可以生成最新的股票价格,即使没有用户对此股票感兴趣。


那么一个是工厂,另一个是运行实例?那么它不应该被称为“可观察工厂”以减少混淆吗? - Dmitri Zaitsev
26
喜欢这个比喻-现在它会一直在我脑海中留存。 - Gruff Bunny
我们可以这样说,Hot observables 是 Eager loaded,而 Cold observables 是 Lazy loaded 吗? - Dhiren
你真是个天才!谢谢,我再也不用谷歌搜索了:D - jayeshsolanki93
1
这个与电影相关的比喻确实很贴切。谢谢。 - Peterstev Uremgba

70

热的可观察对象是在您未订阅可观察对象时推送事件的对象。例如鼠标移动、计时器滴答等。冷的可观察对象是在订阅后才开始推送事件,并且如果再次订阅,则重新开始。


我很惊讶看到这个发布了,我只写了一半,而且这告诉你的只是你已经知道的内容,很抱歉。今晚太晚了,无法完成。明天我会更新代码示例。 - Richard Anthony Freeman-Hein
2
孩子们?18年后再来看看。;^D(顺便说一句,我喜欢这个开始...一个好的、逐步的例子(而不是Lee的一个博客链接)会被赞赏,即使在2019年!) - ruffin
6
这个答案是错误的。热型的可观察对象并不是急切的。不同之处在于,冷型的可观察对象会为每个订阅创建一个观察者,而热型的可观察对象只会在至少有一个订阅者时才创建一个单一的观察者。 - Steve
@Distortum 在当时和当下的情境下是正确的。热可观察对象通常是在没有订阅者的情况下触发事件的事物。我从创建者那里得到了这个信息。也许现在已经改变了,但是在发布时它是正确的,并且对于该情境来说足够了。请随意扩展答案。 - Richard Anthony Freeman-Hein

41

希望这可以帮助到您。

您能为这些术语给出全面的定义吗?

请看我的博客文章:https://leecampbell.com/2010/08/19/rx-part-7-hot-and-cold-observables

在热Observable上调用Publish或在冷Observable上调用Defer有意义吗?

不,我想不出有意义的情况。

热/冷转换的方面有哪些 - 例如,您会丢失消息吗?

当Observable是Hot时,可能会“丢失”消息,因为“事件”会发生而不管订阅者是否存在。

IObservable和IEnumerable的热和冷定义之间有什么区别吗?

我真的不理解这个问题。但我希望这个比喻能够帮助理解。我将一个Hot Observable与急切评估的IEnumerable进行比较。即List或Array都是急切评估的,即使没有任何枚举器对它们进行枚举,它们也已经被填充。从文件或数据库获取值的yield语句可以使用Yield关键字进行惰性评估。虽然lazy可能很好用,但默认情况下,如果第二个枚举器对其运行,则会重新评估它。将这些与Observables进行比较,Hot Observable可能是事件(按钮单击)或温度馈送;这些事件将发生而不管是否订阅,并且如果对同一Observable进行多个订阅,则也将共享。Observable.Interval是Cold observable的一个很好的例子。只有在进行订阅时才会开始产生值。如果进行多个订阅,那么序列将被重新评估,并且“事件”将在不同时间发生(取决于订阅之间的时间)。

在编写热或冷程序时应考虑哪些常规原则?

请参考第一点中的链接。我还建议您了解使用Publsh与RefCount配合使用的情况。这可以让您拥有Cold Observables的惰性求值语义,同时也能共享Hot Observables获得的事件。

关于热/冷可观察对象,还有其他的提示吗?

动手实践并尝试使用它们。一旦您已经花费30分钟以上阅读了它们的相关资料,那么投入时间进行编码会比再读更加有效 :)

6
你的博客链接失效了。 - Nguyen Minh Binh
链接对我来说看起来没问题。可能是因为公司防火墙的原因导致你被阻止了?另外两个链接是http://leecampbell.blogspot.co.uk/2010/08/rx-part-7-hot-and-cold-observables.html或者更近期的http://introtorx.com/Content/v1.0.10621.0/14_HotAndColdObservables.html。 - Lee Campbell
1
这里有一个使用案例,用于推迟冷可观察对象:http://blog.danlew.net/2015/07/23/deferring-observable-code-until-subscription-in-rxjava/ - bryant1410
这是一个延迟热可观察对象的示例。RxJava的Just是热/急切的。 - Lee Campbell
正确的链接是:https://leecampbell.com/2010/08/19/rx-part-7-hot-and-cold-observables/(在你的回答中是:http://leecampbell.blogspot.com/2010/08/rx-part-7-hot-and-cold-observables.html) - daymannovaes

17

并不打算给出全面答案,我想用最简单的方式总结一下我自问这个问题以来所学到的内容。

热可观察对象是事件的精确匹配。在事件中,即使没有订阅者监听,值通常也会被馈送到处理程序中。所有订阅者都接收相同的值集。由于遵循“事件”模式,热可观察对象比冷可观察对象更易理解。

冷可观察对象也像一个事件,但有一个小变化-冷可观察对象的事件不是共享实例上的属性,而是每次有人订阅时从工厂生成的对象的属性。此外,订阅启动了值的生成过程。因此,多个订阅者被隔离开来,每个订阅者接收自己的值集。

RX初学者常犯的最常见错误是使用某些状态变量(例如累计总数)在函数内创建一个冷可观察对象(或认为自己正在创建一个冷可观察对象),而没有将其包装到.Defer()语句中。结果,多个订阅者共享这些变量,并在它们之间引起副作用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接