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

Pause throttled streams

umanamente opened this issue · comments

I have a throttled stream:
var MyTimer = Bacon.fromArray([1,2,3,4,5,6,7,8,9,10]).bufferingThrottle(1000);
So it ticks once a second.
I also have a "pause" button mapped to a property:

var PropertyPaused = $("#pause").asEventStream("click")
        .map(function(event) {
            is_paused = !is_paused;
            return is_paused;
        }).toProperty(is_paused);

When I press pause, timer must be paused. When I unpause, it should continue ticking like a normal timer.
I've tried to use .holdWhen(PropertyPaused). But when I unpause the stream, it doesn't throttle events:

What I need:
  1..2..3.|--- pause ----|..4..5..6..7..8..9..10
How it works:
  1..2..3.|--- pause ----|..45678910..........

Could you please add a feature to pause throttled streams in a proper way?

I see what you're looking for and it makes sense. There's currently no method for doing this with a one-liner. To implement this properly, you'd need to capture all incoming events along with their timestamps so that you can pause/resume "playback". Certainly doable, but not trivial. Why not write the implementation yourself and submit a Pull Request? :)

I'm new with Bacon, so I can't implement it myself.

I see another possible approach:

var MyTimer2 = Bacon.fromArray([1,2,3,4,5,6,7,8,9,10]).flatMapConcat(function(val){
    return Bacon.once(val).delay(1000)/*.holdWhen(PropertyPaused)/**/;
});

but it doesn't work with holdWhen (only first event fired). It seems that holdWhen doesn't pass End event, so the spawned stream never ends.

I've found a workaround, but it's monstrous:

var MyTimer3 = Bacon.fromArray([1,2,3,4,5,6,7,8,9,10]).flatMapConcat(function(val){
  var is_ended = false;
  return Bacon.fromPoll(500, function(){
    if(is_ended){
        return new Bacon.End("END!");
    }
    if(!is_paused){
        is_ended = true;      
        return new Bacon.Next(val);
    }    
  }).filter(function(v){
    return typeof(v)!="undefined";
  });
});

See https://jsfiddle.net/492goy34/

I've fixed the problem with holdWhen() (see pull request #666). Now it's simple:

var MyTimer2 = Bacon.fromArray([1,2,3,4,5,6,7,8,9,10]).flatMapConcat(function(val){
    return Bacon.once(val).delay(1000).holdWhen(PropertyPaused);
});