函数式响应式编程相对于事件侦听器的优势

Advantage of Functional Reactive Programming over event-listeners

本文关键字:侦听器 相对于 响应 编程 函数 事件      更新时间:2023-09-26

我听说过很多关于函数式响应式编程的事情,所以我决定看看它到底有什么了不起。通过bacon.js文档,似乎主要的区别在于,不是在组件上设置事件侦听器,而是在组件上创建事件流,并将事件处理程序传递到流中。换句话说,我所做的只是将事件处理程序从组件移动到事件流。就是这样吗?如果是这样,那么这样做的最大优势是什么?

函数式响应式编程(FRP)的关键点是一个语法属性:

值的动态行为在声明时间指定。

例如,考虑一个可以通过按按钮向上或向下计数的计数器。在命令式风格中,您可能会这样写:

counter := 0                               -- initial value
on buttonUp   = (counter := counter + 1)   -- change it later
on buttonDown = (counter := counter - 1)

首先,用初始值声明计数器。然后,在代码的后面部分,更改该值。现在,如果有人问你"在任何给定时刻,counter的值是多少?",你必须查看代码中引用counter的所有部分,因为这是它可能被改变的地方。

相反,当使用FRP样式代码时,可以通过查看代码中的一个位置来回答这个问题:声明counter的地方。例如,在Haskell中,可以将计数器写成

counter :: Behavior Int
counter = accumulate ($) 0
            (fmap (+1) buttonUp
             `union` fmap (subtract 1) buttonDown)

右边包含了在任何给定时刻counter的值所需的所有信息。特别是,您可以看到它可以通过buttonUpbuttonDown进行更改,这就是。你不需要筛选你的代码,寻找计数器可能改变的地方,不,只要看看它的声明并从那里开始跟进就足够了。

这就是为什么FRP代码比基于事件的意大利面条代码更不容易出现bug的原因。

参见我的threenpenny -gui库的一些初步文档

是这样吗?

。它是关于拥有事件流。最后,您仍然需要将侦听器附加到它们上以执行效果,但是在源和目标之间,您有一个非常强大的抽象。

这样做的最大优势是什么?

事件流确实有很多高阶函数可以很容易地处理它们,对于来说,组合事件流而不需要写出所有容易出错的样本代码。

就像文档说的那样,bacon

把你的事件面条变成干净的声明性的风水培根,从命令式切换到功能性。这就像用函数式编程概念(如mapfilter)替换嵌套的for循环。停止处理单个事件,转而处理事件流。将你的数据与mergecombine相结合,并使用flatMapcombineTemplate等更重的武器。