为什么bacon.js可观测量被分类为懒惰序列?

时间:2014-05-28 05:50:21

标签: observablecollection bacon.js

我对延迟序列的理解是,在程序访问数据之前,它们不会将数据加载到内存中。所以我可以看到,如果有一个大的数字列表等待被消耗,这将是有意义的,但是当迭代器调用下一个方法时,序列只从生成器中提取数据。

但只要生产者将项目推送给他们,observable就会将项目附加到自己身上。因此,当消费者要求时,它不像序列加载数据,它会在生产者发送它时加载它。那么可观察的懒人是什么方式?

2 个答案:

答案 0 :(得分:1)

Bacon.js Observables中有两种懒惰:

  1. Observable不会注册到其基础数据源(例如,AJAX提取),直到至少有一个Observer。这种懒惰实际上为您提供了自动资源管理,即根据需求自动打开和关闭与数据源的连接。此外,如果有多个观察者,则只使用与数据源的单个连接,并且共享结果。

  2. Observable不会评估传递给mapcombine等的函数,直到实际使用该值为止。因此,如果您在为map提供的函数中进行昂贵的计算,并且仅在一秒钟内对流进行一次采样,则只会对这些值进行实际评估。

  3. 你不能得到的是背压管理。因此,如果你是数据源,比如可观察a,那么顺序生成无限值,你可以

    • 立即使用a.onValue
    • 处理它们
    • 首先使用a.take(1000).onValue
    • 取1000个
    • 使用a.takeUntil((x) -> x > 1000)).onValue
    • 获取某些条件

    但你不能影响来源产生价值的比率,因为Bacon.js没有办法告诉消息来源我以后会对更多的价值感兴趣,我会告诉你当&#34 ;.我一直在考虑添加这样的东西,但这会使问题复杂化。

    作为底线,我说Bacon.js不是您处理无限列表的理想库,例如Haskell风格。和AFAIK,也不是任何其他Javascript FRP lib。

答案 1 :(得分:0)

延迟序列是在最后一次评估其元素的序列。对它们有用的是,您可以传递序列,甚至可以对其执行操作,而无需评估其内容。

由于您不评估序列,您甚至可以创建无限序列;只要确保你没有评估整个过程。例如,下面的Haskell程序创建一个无限的自然数序列,然后懒洋洋地将每个元素乘以2,产生无限的偶数序列,然后获取前5个元素,评估它们(并且只有它们):

take 5 (map (*2) [1..])
-- [2,4,6,8,10]

基本上,使用惰性序列和一组对它们起作用的函数(如map),您可以编写以可组合方式创建和处理潜在无限数据流的程序。

顺便提一下,这正是(功能性)反应式编程的意义所在。可观察对象可被视为可能无限的对(value, timestamp)流。对可观察对象(例如map)的操作只是根据原始流创建另一个流。将消费者附加到一个可观察者会评估已经发生的事件的元素",而其余部分则不予评估。

例如,培根observable.map可以实现为一种功能,可以将功能懒惰地应用于“价值”。流的一部分(再次在Haskell中):

map f = Prelude.map (\(value, tstamp) -> (f value, tstamp))

observable.delay会增加“时间戳”的延迟时间。部分:

delay dt = Prelude.map (\(value, tstamp) -> (value, tstamp + dt))

其中Prelude.map只是一张普通的"地图"对懒惰序列起作用。

希望我再也不会让你感到困惑!