RxJS for Bacon.js Users

Bacon.js is a popular Functional Reactive Programming (FRP) library which was inspired by RxJS, ReactiveBanana among other libraries. If you're not familiar with FRP, Conal Elliott summed it up nicely on StackOverflow so no need to repeat that here.

Bacon.js has two main concepts, Event Streams and Properties, which we will map to RxJS concepts.

Contents

Common API Methods

Event Streams

In Bacon.js (and RxJS for that matter), an EventStream represents a stream of events. It is an Observable object, meaning that you can listen to events in the stream using, for instance, the onValue method with a callback.

Creating Event Streams

Bacon.js

Because Bacon.js is optimized for jQuery and Zepto, you can use the $.fn.asEventStream method to easily bind to create event streams.

For example we can get the clickable element, listen to the click event, and then we can subscribe via the onValue method to capture the clicks.

var clickable = $('#clickable').asEventStream('click');

clickable.onValue(e => console.log('clicked!'));

The support goes above just standard support, but also selectors and an optional argument selector which transforms the arguments of the event to a single object.

$("#my-div").asEventStream("click", ".more-specific-selector")

$("#my-div").asEventStream("click", ".more-specific-selector", (event, args) => args[0]);

$("#my-div").asEventStream("click", (event, args) => args[0]);

RxJS

It's very similar in RxJS core. Until recently, this feature was reserved for external libraries such as RxJS-jQuery, RxJS-DOM, RxJS-Dojo and RxJS-MooTools. RxJS 2.2 introduced two ways to bind to events with fromEvent and fromEventPattern so that bridge libraries are strictly not as necessary as they used to be.

For example, we can recreate the binding to the clickable element for the click event, and then call subscribe with a function which listens for each time the clickable is clicked.

var clickable = $('#clickable');

var clickableObservable = Rx.Observable.fromEvent(clickable, 'click')
    .subscribe(() => console.log('clicked!'));

In addition, RxJS also supports for event argument transformers for additional data. For example, if a Node.js EventEmitter emits more than one piece of data at a time, you can still capture it.

var Rx = require('rx'),
    EventEmitter = require('events').EventEmitter;

var e = new EventEmitter();

Rx.Observable.fromEvent(e, 'data', args => ({ first: args[0], second: args[1] }))
    .subscribe(data => console.log(`${data.first}, ${data.second}`));

e.emit('data', 'foo', 'bar');
// => foo,bar

Querying Streams

Event Streams support higher ordered functions much as RxJS does such as map, filter and more, although supports a more Underscore/Lo-Dash style than the callback selector style found in RxJS.

var plus = $("#plus").asEventStream("click").map(1);
var minus = $("#minus").asEventStream("click").map(-1);

// Combine both into one
var both = plus.merge(minus);

both.onValue (x => { /* returns 1 or -1 */ });