繁体   English   中英

Bacon.js控制流与其他流的缓冲

[英]Bacon.js control buffering of stream with other stream

我想在Bacon.js中缓冲一个EventStream的值,就像buffer(closingSelector)在RxJava中的行为一样。 当“控制器流”(RxJava方法中的closingSelector)发出新值时,事件缓冲区将被刷新。

所以我希望流输出与stream.bufferWithTimeOrCount类似,但不是用时间间隔或事件计数来控制缓冲,而是想控制其他流的缓冲。

在Bacon.js中有一种简单的方法可以实现吗?

Bacon.holdWhen可用时大约0.7.14几乎可以满足您的需求,尽管缓冲事件是逐个发出的:

stream.hold当(阀门)暂停并缓冲事件流,如果阀门中的最后一个事件是真的。 当阀门变得麻痹时,所有缓冲的事件都会被释放。

如果您需要将缓冲事件作为单个事件发出,则可以尝试以下操作:

// source streams
var sourceObservable = Bacon.interval(1000);
var closingSelector = new Bacon.Bus();

// Constructing a new Observable where we're going to keep our state.
// 
// We need to keep track of two things: 
//   - the buffer that is currently being filled, and
//   -  a previous buffer that is being flushed.
// The state will then look like this:
//   [ buffer, flushed]
// where both buffer and flushed is an array of events from the source observable.

// empty initial state
var initialState = {buffer: [], flushed: []}

// There are two operations on the state: appending a new element to the buffer 
// and flushing the current buffer:

// append each event from the source observable to the buffer,
// keeping flushed unchanged
var appends = sourceObservable.map(function(e) {
   return function(state) {
       state.buffer.push(e); return state; 
   } 
});

// each event from the closingSelector replaces the `flushed` with 
// the `buffer`'s contents, inserting an empty buffer.
var flushes = closingSelector.map(function(_) {
   return function(state) { return {buffer: [], flushed: state.buffer} }
})

// merge appends and flushes into a single stream and apply them to the initial state
var ops = appends.merge(flushes)
var state = ops.scan(initialState, function(acc, f) { return f(acc) });

// resulting stream of flushed events
var flushed = state.sampledBy(closingSelector).map(function(state) { return state.flushed })

// triggered with `closingSelector.push({})`
flushed.onValue(function(x) { console.log("flushed", x) })

Bacon.js没有你需要的功能,所以我查看了bacon.js源代码并编写了一个改进版的holdWhen

Bacon.EventStream.prototype.bufferUntilValue = function(valve) {
var valve_ = valve.startWith(false);

  return this.filter(false).merge(valve_.flatMapConcat((function(_this) {
    return function() {
        return _this.scan([], (function(xs, x) {
            return xs.concat(x);
        }), {
            eager: true
        }).sampledBy(valve).take(1);
    };
  })(this)));
};

要查看此操作,请查看此jsFiddle

stream.holdWhen(valve)看起来几乎就是你想要的。 它与buffer(closingSelector)工作方式略有不同:它不是一直缓冲来自closingSelector事件缓冲事件,而是根据value流中的最后一个值来切换缓冲。

也许你可以使用holdWhen ,但如果你想要像buffer(closingSelector)这样的行为,你可能会这样做:

var result = sourceStream.holdWhen(closingSelector.flatMap(function(){
  return Bacon.fromArray([false, true]);
}).toProperty(true));

在来自closingSelector每个事件中,我们在value流中生成两个事件,其值为truefalse ,即关闭缓冲(触发刷新)然后立即将其重新打开。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM