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

throttleImmediate

Phoscur opened this issue · comments

I'd like to filter my stream to issue update events (rerequesting resources) so I want to debounceImmediate but then just to be sure, issue another update if something changed in the debounce period.
Example:

var throttled = source.throttleImmediate(2)
source:    asdf----asdf----a--
throttled: a-d-f---a-d-f---a--

How would you accomplish this currently? With a custom bacon operator?

Isn't simply Bacon.mergeAll(source.debounceImmediate(2), source.debounce(2)) ?

var source = Bacon.sequentially(250, 'asdfghjk'.split('')).concat(Bacon.sequentially(250, 'asdfghjk'.split('')).delay(5000));
var throttled = Bacon.mergeAll(testSeq.debounceImmediate(990), testSeq.debounce(990));
source.log(':'); throttled.log('t:');
// asdfghjk_____asdfghjk   
// a___g___k____a___g___k

Merging debounceImmediate and debounce gives us throttleImmediate - seems like the right solution.
Thanks @semmel !

Reopen if you would like to add this to the Bacon API.

I think it would make sense to add into the API. Pull Request anyone?

@semmel the merging produces two events in case only one was fired, we might need some more code here to prevent this.

It is supposed to only fire a second event, if there was one in the debounce period.

@raimohanska @semmel any help concerning this would be very appreciated as this has become an urgent issue for me. I seem to be still not familiar enough with reactive programming or I just have some thought block on this.

The current failing test could be trivially solved by filtering duplicates out. But how does that work on more complex event objects, an isEqual comparator would need to be supplied?

Resolved urgency of the issue by optimizing input and update processing at the end of the stream. Events are more detailed now.

Still considering to just debounce the eventstream, possibly with a partially random time interval to stagger downloads a bit, what do you think, do you need more information on the usecase?

Maybe this:

Observable.prototype.throttleImmediate = (delay) => 
  this.flatMapFirst(first => B.once(first).concat(B.later(delay).filter(false)))

Might be worth trying?

@raimohanska as you can see in #712, I already tried to create a debounceImmediate variant and borrowed from the tests.

debounceImmediate does not solve the usecase:
Using a high delay, e.g. one Minute, all subsequent Events in the delay will be missed, and the data returned from the "immediate" request, will be outdated.

Oh, you want to include the last event in the batch too. Should have looked at your diagram up there.

How about this: https://codesandbox.io/s/o91z082j5y

Got a bit complicated, which is disappointing. Are we missing some key methods that would make this easier?

Before I saw your PR, I added a shortened version of that sandbox code to my PR #712. It works and covers EventStream tests. I was able to leave out the part merging the sampler with the silence..

Properties still output a duplicate though. @raimohanska can you explain why?

Also the doubleEdgedDebounce of which you forked the sandbox from would suit my needs - why are they so different?

How would you like to land one of these doubleEdged implementations?

The leadingThrottle implementation works for my usecase, but it doesn't skip events as I first intended.