baconjs / bacon.js

Functional reactive programming library for TypeScript and JavaScript

Home Page:https://baconjs.github.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[API Addition] bufferUnderCondition

semmel opened this issue · comments

What do you think of such a bufferUnderCondition-like function?

It buffers source stream values when the condition is truthy. When the condition is false or the condition has ended, any accumulated values are flushed and subsequent source values are let passed. The resulting stream ends when the both the condition and the source stream have ended.
As marble diagrams:

/* c: condition (t -is true, f means false), s: source, r: result
 *
 * time:         200         400         600         800         1000
 * c: t-----------f-----------t-----------f-----------t-----------f<end>
 * s: ---0--1--2----3-----4-----5678-----------9----------10<end>
 * r: -----------0123-----4-------------5678---9-----------------10<end>
 *
 * c: ---t----<end>
 * s: x---x--x--x---x--<end>
 * r: x--------xxx--x--<end>
 *
 * c: ---t--------------<end>
 * s: x---x-y-z<end>
 * r: x-----------------xyz<end>
 */

I could not figure a way to do it simply with the existing API.

My implementation is goes along Bacon.mergeAll(source, condition).withStateMachine. However a PR is blocked because I cannot get the tests running, partly because of #727.

Do you think it is worth pursuing a PR?

How about holdWhen?

Hmm. holdWhen seems to be the solution.
But I was under the inpression, that as .takeWhile and .takeUntil it would work only once.
I now see that it does not, except here I cannot make it work:

var propBus = new Bacon.Bus();
var valve = propBus.toProperty(true);
var stream = Bacon.repeatedly(2000, [0, 1, 2, 3, 4, 5])
.flatMapConcat( v => Bacon.once(v).holdWhen(valve) );
var unsub = stream.onValue(console.log.bind(console));
// ... let some time pass to allow for buffering
propBus.push(false);
// -> 0 1 2 3 4 5 0
propBus.push(true);
// -> 1 2 3 4 it continues to emit values no matter what the valve is !

Yes, valve needs to be a "hot" (or "eager") observable! It works now.
I already have a utility function eagerUntil for that purpose

Bacon.Property.prototype.eagerUntil = function(observable){
	this.takeUntil(observable).onValue(function(){});
	return this;
};

... but I always forget to attach it to my properties!
😥

Thank you very much!