【发布时间】:2013-08-15 13:44:35
【问题描述】:
有人说 FRP 是关于在不显式管理状态的情况下处理事件流。这个人,例如:
http://www.slideshare.net/borgesleonardo/functional-reactive-programming-in-clojurescript
其他人通过指出完全通过副作用进行编程的困难来激励 FRP,就像使用异步回调必须做的那样。
http://cs.brown.edu/~sk/Publications/Papers/Published/mgbcgbk-flapjax/
然而,在尝试使用 FRP (flapjax) 时,我一直遇到同样的问题:无法通过副作用处理状态,除非明确表示。
例如,动画队列。更改到达事件流。当第一个更改到来时,我需要排队等待在未来某个时间发生的抽奖(例如使用 window.requestAnimationFrame),并安排累积现在和未来抽奖事件之间的更改。当draw事件发生时,我需要绘制累积的变化。
这大约是六行代码,使用带有观察者模式的命令式样式,但我找不到在 FRP 中表达这一点的合理方式。唯一接近的事情是关闭共享状态上的相关事件流,并通过副作用显式管理状态和呈现事件。这几乎不是命令式回调的改进。
这在 FRP 中应该如何处理?
这是一个用于关闭状态的flajax实用程序:
function worldE(init, handlers) {
var r = fj.receiverE();
fj.forEach(function(h) {
h[0].mapE(function (ev) {
r.sendEvent(init = h[1](init, ev));
});
}, handlers);
return r;
}
这里是在动画循环中使用的:
function initialize(opts) {
var blitE = fj.receiverE();
function accumulate(state, data) {
if (!state.queued) {
window.requestAnimationFrame(blitE.sendEvent);
}
return {queued: true, changes: _.extend({}, state.changes, data)};
}
function dodraw(state, _) {
draw(state.changes);
return {queued: false, changes: {}};
}
worldE({queued: false, changes: {}},
[[opts.data_source, accumulate], [blitE, dodraw]]);
}
注意事项:与等效的回调代码相比,它更大、可读性和可维护性更差。它仍然需要显式管理状态。它通过副作用起作用。
在 FRP 中是否有更好的方法来做到这一点?不同的模式,还是不同的库?
【问题讨论】:
-
我不熟悉flajax,但你也可以试试RxJs。它可能有不同的、更好的语法。另外,如果您想查看一些更复杂的 FRP 示例,请查看 ELM 语言 elm-lang.org
标签: javascript reactive-programming frp