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

sync/async subscription behavior differs after slidingWindow()

vujicP opened this issue · comments

I get a different behavior depending on if I subscribe synchronously or asynchronously to a stream that is using slidingWindow(): https://jsfiddle.net/j2mLpuqw/

Not sure if am missing something but I expected that the behavior of the async subscriber is independent of subscriptions to other streams. The subscription outside setTimeout() works as expected. With .changes().filter(...) I get the expected behavior but this solution would not work for a stream with more states than true/false.
Another example with combined streams: https://jsfiddle.net/zwn05cxu/

Is that a bug or is it possible to get the async subscription to work the same way as the sync subscription?

Looks like the combo Bacon.fromArray().bufferingThrottle is somehow broken.
Replacing Bacon.fromArray([]) with Bacon.sequentially(0, []) seems to fix both examples.

I rarely use Bacon.fromArray in real code - just for doodling in the REPL.
If I recall correctly Bacon.fromArray also is something of an alien in baconjs because it kind of synchronously emits events which causes all kinds of trouble. That behaviour was already changed in the past when the major version of baconjs bumped, I guess.

Do you really need to fire your data items using Bacon.fromArray?

The stream I use is created with Bacon.fromBinder. Seems to happen there too: https://jsfiddle.net/7es20dtw/. I mean there are ways to circumvent this exact case, just wondering if I was missing some idea here.

Some ideas regarding the example with Bacon.fromBinder(producerFn) :

  1. Bacon streams are lazy. That means until there is a subscriber for the stream, the producer function is not called. This is part of the explanation why the async subscription of derived works if boolStream itself has not yet produced any values in case the boolStream subscription is commented out.
  2. slidingWindow produces a Bacon.Property. That is a stream which has a concept of a current value to help when combining with other Bacon.Properties using binary functions. (It prevents misleading updates in diamond shaped data paths, There is a helpful section called "Why is my property not updated somewhere in the baconjs FAQ.)

So when you comment in the synchronous subscription of derived (your Property), derived maintains a current value, which is later, when the async subscription kicks in, reproduced. Thus the async sub works.

As explained in my first point the sync subscription of the base boolStream ( a Bacon.EventStream) causes the producerFn to produce values - but without any subscription to the derived Bacon.Property that pipeline is completely dead (or lazy) and those early produced values are nowhere buffered or stored.

Does that make sense?

P.S. It's always beneficial to ponder a little if my data stream is an event stream or a property stream.

Thank you now it's clear! The moment when a subscription is reaching through first to boolStream matters. So when boolStream is a property like here https://jsfiddle.net/4b6j0Lvo/1/ then at the time of the async subscription to derived boolStream has a latest value and produces the result I expected.