baconjs / bacon.js

Functional reactive programming library for TypeScript and JavaScript
https://baconjs.github.io
MIT License
6.47k stars 331 forks source link

Bacon .zip documentation misleading #606

Open cefn opened 9 years ago

cefn commented 9 years ago

I have discovered that Bacon.zip does not actually call the zipping function when I try to use toPromise() to proceed to the last event in a zipped stream.

This is very surprising given the documentation for .zip which asserts that the fromArray stream in the example "# produces values 4, 6" when that rather depends on what you do with the stream, and it isn't made at all clear how to actually cause it to produce those values.

I believe this issue should be clarified in two ways.

Having looked at this for quite a while, I still cannot fathom what concrete steps can be taken to avoid the laziness in the case of using toPromise().

I have attempted...

BACKGROUND: I am trying to use Bacon to assert a message sequence sent asynchronously over an MQTT websockets server. Here is a Gist which underlines the issue around Laziness.... https://gist.github.com/cefn/9633e715b6677600b5eb

When running this Mocha test suite, the 'deepEqual' function is in fact called only once, leading to a console report like...

Testing ["oldmacdonald/farm/duck","'Quack'"] versus ["oldmacdonald/farm/duck","'Quack'"]... Stream finished

cefn commented 9 years ago

I have found a workaround as demonstrated by the gist at... https://gist.github.com/cefn/7fd3504a0b29575f3b6f ...which involves using sequentially(0, ...) to ensure the stream delivers sequences and ends, zipAsArray to deliver individual pairs, onValues(...) to make the demand for side-effects explicit, then a toPromise() to make the streams flow until the end within the test itself.

This causes the sequence to proceed as it should... Testing ["oldmacdonald/farm","['sheep','pig','cow','duck']"] versus ["oldmacdonald/farm","['sheep','pig','cow','duck']"]... Testing ["oldmacdonald/farm/sheep","'Baa'"] versus ["oldmacdonald/farm/sheep","'Baa'"]... Testing ["oldmacdonald/farm/pig","'Oink'"] versus ["oldmacdonald/farm/pig","'Oink'"]... Testing ["oldmacdonald/farm/cow","'Moo'"] versus ["oldmacdonald/farm/cow","'Moo'"]... Testing ["oldmacdonald/farm/duck","'Quack'"] versus ["oldmacdonald/farm/duck","'Quack'"]... Stream finished ...and tests also fail properly when the message sequences do not match.

For reference, using fromArray(...) instead of sequentially(0, ...) actually means the underlying streams never cause the zipped stream to terminate and I don't know why (this is perhaps the original issue which was causing my test suite to hang, which began my investigations, I'll raise this as a separate documentation issue).

In terms of where this could be documented I wonder whether the very general title "Why isn't my subscriber called" could be more of a troubleshooting guide, indicating the several ways in which a subscriber you might expect to be called is in fact not called (including this kind of laziness).

The example provided at the link below is only one way, and relates only to synchronous array-based streams. https://github.com/baconjs/bacon.js/wiki/FAQ#why-isnt-my-subscriber-called

Apologies if these issues are in fact documented somewhere that I haven't found, yet.