如何利用scan()更加清晰

时间:2014-12-07 11:46:37

标签: javascript reactive-programming frp bacon.js

我想使用bacon.js创建一个简单的网页。它应该有一个按钮,通过鼠标点击切换布尔状态。 设置流后,应通过将对象发送到init流来初始化应用程序。在这里,我只是发送切换(false)所需的初始布尔状态。 代码看起来像这样(我伪造了按钮点击和初始化):

// Helper function
var neg = function (a) { return !a; }; 

// Fake of initialization stream. End after one element
var init = Bacon.sequentially(500, [false]);  
// Fake of button click event stream.
var click = Bacon.repeatedly(1000, [{}]); 

var toggle = init.concat(click).scan(null, 
    function(a, b) { return a === null ? b : neg(a); }).skip(1).toEventStream();

toggle.log();
// Output: false, true, false, true, ....

上面的代码(jsFiddle)按预期工作,但我不喜欢toggle流创建行非常复杂。

如果可以省略种子值(从流中取出),如果scan返回EventStream而不是Property,我可以写:

var toggle = init.concat(click).scan(neg);

这可以读得更好。或者,如果可以将种子作为流提供,我可以写:

var toggle = click.scan(init, neg);

您有什么建议可以让代码更清晰吗? 是否有使用scan的替代解决方案? 我应该让我自己使用scan方法吗?

1 个答案:

答案 0 :(得分:1)

如果您阅读我之前写的内容,请忽略。它。 :)这种情况正是flatMap的用途:创建流的流。使用flatMap。

// Helper function
var neg = function (a) { return !a; };

// Fake of initialization stream. End after one element
// Note the use of `later` instead of `sequentially`, by the way
var init = Bacon.later(500, false);

// Fake of button click event stream.
var click = Bacon.repeatedly(1000, [null]);

var toggle = init
    .flatMap(function(initVal) { return click.scan(initVal, neg) });

toggle.log();