首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用FRP管理状态

使用FRP管理状态
EN

Stack Overflow用户
提问于 2013-08-14 03:32:11
回答 3查看 1.1K关注 0票数 1

有人说,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实用程序:

代码语言:javascript
复制
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;
}

这里它被用在一个动画循环中:

代码语言:javascript
复制
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中做到这一点?是不同的模式,还是不同的库?

EN

回答 3

Stack Overflow用户

发布于 2013-09-04 02:25:40

我不熟悉Flapjax,但是看一下文档,您可以使用collectE创建一个累积状态的流。然后,使用receiverEsendEvent创建第二个animationFrame事件流。

最后,模拟bacon.js的sampledBy (https://github.com/baconjs/bacon.js/wiki/Diagrams#sampledby)来创建第三个animationFrame流,即状态元组。

票数 1
EN

Stack Overflow用户

发布于 2013-10-23 17:43:52

这里更多的是flapjax :不是使用sampledBy,而是使用snapshotE,它将在每个帧事件上对已经收集的更改数组进行快照。查看你的谷歌群组主题,我已经为它写了一些代码。

票数 0
EN

Stack Overflow用户

发布于 2015-08-26 12:45:48

FRP完全是关于管理状态的。但这是关于没有时间来管理状态。要做到这一点,您必须将状态保持在树或图中。这可以防止任何旧的代码在某个随机的时间点改变它的

In FRP状态仅在父节点触发更新时更新。当发生这种情况时,将使用事件值(和任何其他父值)来计算新的节点值。

上面blandw的答案是正确的,因为collectE是你想要的。

在collectE中,此节点的前一个值是在触发其父节点时提供的。这允许您存储所需的任何状态,例如更改的集合。但此集合仅在父事件已激发时才会更新。

因此,通过将状态的变化限制在父母更新时,您可以节省大量的hassel。用一个基本的例子很难看出这一点。当你在一个大型项目中工作时,这一点会变得更加明显。

然而,为了更新blandw的答案,除了从非receiverE系统中获取事件之外,不要出于任何原因使用frp。这不应该发生在FRP图的中间,而只能作为没有父节点的顶级节点。在任何其他情况下使用它都违反了FRP的全部要点。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18217621

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档