There are many functions in most.js that operate on both a Source
and a Sink
, e.g., map()
, which transforms all the events in a stream, acts as a Sink
by consuming events, and as a Source
when producing new event values after applying a function to them. observe()
is an example of a particular kind of Sink
that consumes events, and passes them to a function you provide.
Most.js Streams
are not active until you consume them, by using one of the "terminal" combinators, observe
, drain
, or reduce
. When you call one of those, the Stream
sends a signal in the Source-Sink
chain to the Source
at the very beginning of the chain. That producer Source
will then begin producing events.
Events are then propagated synchronously from the Source
through the Source-Sink
chain by a simple method call.
Thus, you could provide your own "listener" function to a map
which would transform the events.
There are many factors contributing to most.js’s performance.
The simple call stack event propagation architecture, plus hoisting
try/catch
out of combinator implementations were two of the earliest
and biggest performance improvements.
Most.js performs several other optimizations automatically, based on
algebraic equivalences. A relatively well-known example is combining
multiple map
operations, e.g. map(g, map(f, stream))
, into a
single map
by doing function composition on f
and g
.
The operation also combines multiple filter
operations, multiple
merge
operations, multiple take
and skip
, among others. These
optimizations reduce the number of method calls needed to propagate an
event from producer to consumer.
See this interview with Brian Cavalier
Most.js itself doesn’t handle circular dependencies, but it is totally possible using most-proxy
. Motorcycle does this to create its cycle in its run
package.