flatMapLatest(Bacon.once) is unlike flatMap(Bacon.once)
semmel opened this issue · comments
Matthias Seemann commented
It swallows startWith
and mapEnd
values:
expected behaviour
Calling .startWith
or .mapEnd
multiple times on a stream injects those values just fine in the right order:
Bacon.fromArray([1, 2, 3])
.startWith(-1)
.startWith(-2)
.mapEnd(10)
.mapEnd(11)
.flatMap(x => Bacon.once(x))
// -> -2, -1, 1, 2, 3, 10, 11
observed behaviour
Bacon.fromArray([1, 2, 3])
.startWith(-1) // <- missing after flatMapLatest(Bacon.once)
.startWith(-2)
.mapEnd(10) // <- missing after flatMapLatest(Bacon.once)
.mapEnd(11)
.flatMapLatest(x => Bacon.once(x))
// -> -2, 1, 2, 3, 11
I'd expect .flatMapLatest(Bacon.once)
to behave like .flatMap(Bacon.once)
.
Somehow the following startWith
and mapEnd
events are delivered too quickly to allow Bacon.once
to emit just it's only value.
Matthias Seemann commented
Found a workaround: delay(0)
!
Bacon.concatAll([
Bacon.once(-2),
Bacon.fromArray([1, 2, 3])
.startWith(-1)
.mapEnd(10)
.delay(0), // <---
Bacon.once(11)
])
.flatMapLatest(x => Bacon.once(x))
// -> -2, -1, 1, 2, 3, 10, 11
Matthias Seemann commented
I guess the eagerness of Bacon streams is a problem;
const
// source streams
t1 = Bacon.once("foo"),
t2 = Bacon.once("foo"),
t3 = Bacon.once("foo"),
// derived streams
d1 = t1
.map(s => s.toUpperCase())
.startWith("zero"),
d2 = t2
.map(s => s.toUpperCase()),
d3 = t3
.map(s => s.toUpperCase())
.startWith("zero");
d1.onValue(val => { console.log("d1:", val); });
// -> "zero", "FOO", <end> (Great!)
t2.onValue(() => {});
d2.onValue(val => { console.log("d2:", val); });
// -> "FOO", <end> (Great!)
t3.onValue(() => {});
d3.onValue(val => { console.log("d3:", val); });
// -> "zero", <end> (WTF??!)
It shows that e.g. Bacon.once
breaks referential transparency. I think with lazy reactive streams you can have referential transparency.