Skip to content

bacon has no real throttling/rate-limiting method #317

@michaelficarra

Description

@michaelficarra

Bacon streams have a load of buffering methods, but are strangely missing the one I actually want to use. For comparison purposes, I'll include the diagrams from the documentation here:

var delayed = source.delay(2);
// source:    asdf----asdf----
// delayed:   --asdf----asdf--

var throttled = source.throttle(2);
// source:    asdf----asdf----
// throttled: --s--f----s--f--

var debounced = source.debounce(2);
// source:    asdf----asdf----
// debounced: -----f-------f--

var debounced = source.debounceImmediate(2);
// source:    asdf----asdf----
// debounced: a-d-----a-d-----

What I'm looking for is a function that preserves all events, allowing them to enter the produced stream with a minimum delay between each event.

var limited = source.rateLimit(2);
// source:  asdf----asdf----
// limited: a-s-d-f-a-s-d-f-

The closest I could find was a mention of limitThroughput in #82, which seems not to have been added. This is the implementation I'm using right now:

setTimeout_ = (ms, fn) -> setTimeout fn, ms

bacon.EventStream::rateLimit = (ms) ->
  buffer = []
  outStream = new Bacon.Bus
  draining = no
  drain = ->
    outStream.push buffer.shift()
    setTimeout_ ms, ->
      if buffer.length > 0
        drain()
      else
        draining = no
    return
  @onError (e) ->
    outStream.error e
  @onValue (e) ->
    buffer.push e
    unless draining
      draining = yes
      drain()
    return
  outStream

I know it's probably not very idiomatic, since I am new to bacon, but it is working for me.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions