我一直听到很多关于功能性反应式编程的知识,并决定查看重要的是什么。通过bacon.js文档,似乎主要区别在于,不是在组件上设置事件侦听器,而是在其上创建事件流,并将事件处理程序传递到流中。换句话说,我真正做的就是将事件处理程序从组件移动到事件流。是吗?如果是这样,这样做的最大好处是什么?
答案 0 :(得分:12)
功能反应式编程(FRP)的关键点是语法属性:
值的动态行为在声明时间指定。
例如,考虑一个可以通过按下按钮来计数或减少计数器的计数器。在命令式的风格中,您可能会这样写:
counter := 0 -- initial value
on buttonUp = (counter := counter + 1) -- change it later
on buttonDown = (counter := counter - 1)
首先,计数器以初始值声明。然后,在代码的后面部分中,您可以更改该值。现在,如果有人问你问题"在任何给定的时刻,counter
的价值是什么?",你必须查看引用该名称的代码的所有部分{ {1}},因为它可以在哪里更改。
相反,在使用FRP样式代码时,可以通过查看代码中的一个位置来回答问题:声明counter
的位置。例如,在Haskell中,您可以将计数器写为
counter
右侧包含了解counter :: Behavior Int
counter = accumulate ($) 0
(fmap (+1) buttonUp
`union` fmap (subtract 1) buttonDown)
在任何特定时刻的价值所需的所有信息。特别是,您看到它可以由counter
和buttonUp
,以及进行更改。您不必筛选代码,寻找计数器可能发生变化的地方,不,只需查看其声明并从那里进行跟进即可。
这就是为什么FRP代码比基于事件的意大利面条代码更容易出错的原因。
答案 1 :(得分:7)
是吗?
没有。这是关于拥有事件流。你仍然会在最后附加监听器以执行效果,但是在源和目的地之间你有一个非常强大的抽象。
这样做的最大好处是什么?
事件流确实有很多higher-order functions可以轻松处理它们,并且编写它们而不会写出所有容易出错的样板代码。
作为the docs put it非常好,培根
通过从命令转换为功能,将您的事件意大利面变成清洁和声明性风水培根。这就像用
for
和map
等函数式编程概念替换嵌套的filter
- 循环一样。停止处理单个事件并改为使用事件流。将您的数据与merge
和combine
[并使用]更重的武器[如]flatMap
和combineTemplate
结合起来。