比较core.async和Functional Reactive Programming(+ Rx)

在将Clojure的core.async与所谓的Reactive Extensions (Rx)和FRP进行比较时,我似乎有点困惑。 他们似乎也在处理类似的asynchronous性问题,所以我想知道主要的区别是什么,在哪些情况下,哪一个更受欢迎。 有人可以解释吗?

编辑:为了鼓励更深入的答案我想提出更具体的问题:

  1. Core.async允许我编写同步代码。 但据我了解,FRP只需要一层嵌套的callback(处理逻辑的所有函数都作为parameter passing给FRP API)。 似乎这两种方法都不需要callback金字塔 。 的确,在JS中我必须多次编写function() {...} ,但是主要的问题, 嵌套的callback函数在FRP中也没有了。 我得到它的权利?

  2. FRP与控制stream程完成消息的交stream”您能(某人)给出一个更具体的解释吗?

  3. 难道我不能像我通过频道那样通过玻璃钢的可观察端点吗?

总的来说,我明白这两种方法在历史上来自哪里,而且我也尝试过两种教程。 不过,我似乎被不明显的差异“瘫痪”了。 是否有一些代码很难用其中一种编写代码,而使用其他代码 ? 那build筑原因是什么?

我认为主要的问题是你对解决问题的看法不太一样,因为他们中没有一个正在解决不同步的 “问题”。

抽象

FRP主要思想是变化的传播,考虑完成Excel所做的相同的事情,在层叠中定义彼此相互依赖的单元格,以及当一个单元格发生更改时,将重新计算级联中的所有相关单元格。

core.async主要思想是系统分解,在不同进程中间使用queue思考分离问题,在core.async情况下,而不是队列中有渠道,但你明白了。

所以,去除金字塔码不是任何一种技术的目标,而是在不同的抽象层上进行操作。

关于收集控制stream程

通信和stream量控制的思想是从原来的核心asynchronous岗位上取得的 。

尽pipe有各种各样的使事件/callback变得更清洁的机制(FRP,Rx / Observables),但它们并不改变它们的基本性质,也就是说,在一个事件上运行任意数量的其他代码,可能在同一个线程上运行,告诫,如“不要在你的处理器上做太多的工作”和像“回拨地狱”这样的短语。

如果在事件处理程序中有业务域代码 ,则可以通过重新编写脚本来处理X事件处理以及在发生X时执行的操作

这是core.async解决的问题,因为在中间引入一个队列/通道 ,有助于更好地分离问题。

履行

所有关于callback和传递可观察的端点作为参数的问题只是实现问题,它实际上取决于Rx实现和API。

如果你看看React可重用组件,你真的没有太多的callback地狱,你会得到一个周围传递观察的想法。

最后的想法

即使Rx可以用于模拟任何数据stream,也更常用于UI渲染 Excel,以简化当模型更改时更新视图的方式。

另一方面,当任何两个子系统彼此通信(与队列相同的使用场景)时,可以使用Core.Async来模拟关注点的分离,在UI呈现链上使用它。主要想法是分离:

  • 服务器端事件的生成和处理
  • 这个事件如何影响你的模型

所以你可以把core.asyncFRP放在一起,因为core.async将分离关注点,一旦你的模型被更新, FRP将定义你的级联数据stream。

我认为,至less有一个主要的主要区别是“(FRP)对Rich和控制stream量的沟通”。

callback是被执行的代码。 而且这个执行必须在某个线程中发生。 时间往往是事件发生的时间,线程是注意/产生事件的线程。 如果生产者把消息放在一个频道上,你可以自由地在任何你想要的线程中消费这个消息。 因此callback本质上是一种通信forms,它通过指定callback代码何时何地被执行来控制stream量。 如果因为任何原因必须使用callback,只需使用它们将消息放入队列/通道中即可。

因为core.async不那么复杂,所以只要没有很好的理由去使用这个选项就应该是首选。

Clojure core.async是Go语言的go blocks的一个端口 。 基本概念是表示线程间asynchronous通信的通道。

我们的目标是能够编写正常的顺序代码块,访问渠道获得input,这是无缝地翻译成一个状态机,为您的CSP翻译。

与FRP相比,FRP从根本上来说仍然是callback,它完成了消息与控制stream的交stream。 core.async完全消除了您的代码的callback,并将控制stream与消息传输分开。 此外,在FRP中,通道不是第一类对象(即无法将FRP通道作为FRP通道上的值发送)。

编辑:

回答你的问题:

  1. 是的,很多时候,callback可以被消除,例如重试逻辑,distinctUntilChanged和许多其他的东西,例如:

    var obs = getJSON('story.json').retry(3);

    var obs = Rx.Observable.fromEvent(document, 'keyup').distinctUntilChanged();

  2. 我不确定这是什么,使stream量控制更复杂。

  3. 是的,你可以像通道一样传递一个对象,就像下面的对象一样。

例如,你可以在这里使用带有ReplaySubject的RxJS类似频道的行为:

 var channel = new Rx.ReplaySubject(); // Send three observables down the chain to subscribe to channel.onNext(Rx.Observable.timer(0, 250).map(function () { return 1; })); channel.onNext(Rx.Observable.timer(0, 1000).map(function () { return 2; })); channel.onNext(Rx.Observable.timer(0, 1500).map(function () { return 3; })); // Now pass the channel around anywhere! processChannel(channel); 

为了使它更具体些,请将David Nolen的post中的代码与RxJS FRP示例进行比较

在这里有一篇文章将FRP与CSP进行了比较,但有限的一些例子(这些例子的目的是certificateCSP的好处),最后得出结论: http : //potetm.github.io/2014/01/07/ frp.html