有人说,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)排队一个抽签,并安排从现在到未来抽签事件之间的累积更改。当绘制事件发生时,我需要绘制累积的更改。
这是使用带有观察者模式的命令式样式的大约六行代码,但我找不到一种合理的方式来用FRP来表达这一点。唯一接近的是关闭共享状态上的相关事件流,并通过副作用显式管理状态和呈现事件。这几乎不是对命令式回调的改进。
在FRP中,这应该如何处理?
下面是一个用于关闭状态的flapjax实用程序:
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中做到这一点?是不同的模式,还是不同的库?
发布于 2013-09-04 02:25:40
我不熟悉Flapjax,但是看一下文档,您可以使用collectE创建一个累积状态的流。然后,使用receiverE和sendEvent创建第二个animationFrame事件流。
最后,模拟bacon.js的sampledBy (https://github.com/baconjs/bacon.js/wiki/Diagrams#sampledby)来创建第三个animationFrame流,即状态元组。
发布于 2013-10-23 17:43:52
这里更多的是flapjax :不是使用sampledBy,而是使用snapshotE,它将在每个帧事件上对已经收集的更改数组进行快照。查看你的谷歌群组主题,我已经为它写了一些代码。
发布于 2015-08-26 12:45:48
FRP完全是关于管理状态的。但这是关于没有时间来管理状态。要做到这一点,您必须将状态保持在树或图中。这可以防止任何旧的代码在某个随机的时间点改变它的。
In FRP状态仅在父节点触发更新时更新。当发生这种情况时,将使用事件值(和任何其他父值)来计算新的节点值。
上面blandw的答案是正确的,因为collectE是你想要的。
在collectE中,此节点的前一个值是在触发其父节点时提供的。这允许您存储所需的任何状态,例如更改的集合。但此集合仅在父事件已激发时才会更新。
因此,通过将状态的变化限制在父母更新时,您可以节省大量的hassel。用一个基本的例子很难看出这一点。当你在一个大型项目中工作时,这一点会变得更加明显。
然而,为了更新blandw的答案,除了从非receiverE系统中获取事件之外,不要出于任何原因使用frp。这不应该发生在FRP图的中间,而只能作为没有父节点的顶级节点。在任何其他情况下使用它都违反了FRP的全部要点。
https://stackoverflow.com/questions/18217621
复制相似问题