也许,拿着Bacon.js锤子,一切都开始像钉子一样。但这感觉就像是一个可以用它优雅地解决的问题,而且我还没有足够的经验来解决它。
我的应用程序中的许多地方都需要拥有自己的Bacon.EventStream
。计算这些不同流的值需要一些昂贵的设置和细分:
var stream1 = Bacon.fromPoll(100, function () {
setup(); // expensive
var result = compute1(); // cheap
breakdown(); // expensive
return new Bacon.Next(result);
});
// similar for stream2, stream3, etc.
但是所有这些流的设置和细分都是相同的。因此,将尽可能多的计算组合在一起是有意义的:
Bacon.interval(100, function () {
setup();
// compute value for property1
// compute value for property2
// compute value for property3
// ...
breakdown();
});
但是所有这些独立的流将在代码中的不同位置设置,并且可能具有不同的轮询率等。他们每个人都应该等待下一个可用的窗口来计算它们的值。节奏将由提供此窗口的某个全局流设置。
我一直在玩,JSFiddle here是我迄今为止最好的。{3}}。但是(1)它是不正确的; .skipWhile(property)
似乎只跳过一次,(2)代码已经看起来太复杂了。你能做得更好吗?
修改:我更新了JSFiddle。它现在正常工作。但我想知道我是否使用最佳实践。这段代码可以简化吗?
答案 0 :(得分:1)
我重构了你的小提琴,将窗口计算作为单个函数提供并添加了缓冲,因此传入的值被缓冲直到下一个可用窗口。 See updated jsFiddle.
function calculationWindow(pacing) {
var wantedBus = new Bacon.Bus();
var open = new Bacon.Bus();
var close = new Bacon.Bus();
pacing.filter(wantedBus.toProperty(false))
.onValue(function () {
console.log('<window>');
open.push();
wantedBus.push(false);
close.push();
console.log('</window>');
});
return function (stream) {
wantedBus.plug(stream.map(true))
return close.startWith(true).flatMapLatest(function() {
return stream.takeUntil(open).reduce([], function(arr, val) {
var a = arr.slice(0);
a.push(val);
return a;
}).flatMap(Bacon.fromArray)
})
}
}
在集中的位置执行此操作的好处是,您可以创建一次窗口处理,然后使用结果函数包装任何流。
编辑:如果您不想缓冲值,而只关心最新值,则可以将返回的函数简化为:
return function (stream) {
wantedBus.plug(stream.map(true))
return close.startWith(true).flatMapLatest(function() {
return open.map(stream.toProperty())
})
}