我最近听说了很多关于函数式响应式编程的内容,并决定了解一下这是什么。通过阅读bacon.js文档,我发现主要区别在于,与其在组件上设置事件监听器,我会在它上面创建一个事件流,并将事件处理程序传递到该流中。换句话说,我所做的只是将事件处理程序从组件移到了事件流中。就是这样吗?如果是这样,这样做的巨大优势是什么呢?
我最近听说了很多关于函数式响应式编程的内容,并决定了解一下这是什么。通过阅读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
值在任何给定时刻的信息。特别地,您可以看到它可以通过buttonUp
和buttonDown
进行更改,仅此而已。您不必搜索代码以查找可能更改计数器的位置,只需查看其声明并从那里跟进即可。counter
的值是多少?你必须查看代码中所有引用名称为counter
的部分,因为那里可能会更改它。”——除非你没有将counter
声明为全局变量,而是将其封装在具有明确定义接口的某个对象中。这样,一个简单的counter.getValue()
就可以很可靠地达到效果... - rodrigo-silveiracounter.getValue()
返回的值,您需要在代码中查找所有 counter.setValue(...)
的出现。与之相反,使用 FRP,这些出现都可以从 counter
的声明中访问到。 - Heinrich Apfelmusfilter
/map
/reduce
操作),还在于可组合性。 - Bergi
#text
中的keydown
事件,并注册和取消超时以忽略在300毫秒内输入后跟随的更多输入,并维护最近输入的列表以避免向服务器发送不必要的请求,而只需指定:我想要带有300毫秒暂停的keydown事件,但请勿重复。随着更复杂的逻辑,对比变得更加明显。 - user395760