Functional Reactive Programming
WTF is FRP?

Reactive programming is programming with asynchronous data streams.
- Andre Staltz, creator of cycle.js
Streams, the missing piece
Everything can be a stream
- Events
- Variables
- Data structures
You can actually model every input/output that happens in a browser as a stream (or a stream of streams)
But, can we, effectively, build a program using this notion?
The concept of stream is a good fit for our domain problem, but we need a way of creating, operating, subscribing and reacting to new values emitted by them.
var arr = [1, 2, 3, 4];Streams are a lot like async JS arrays
1
2
3
4
Meet your new friend: The Observable
The first thing we need to understand is that observables are not streams. Actually, you can better understand the observable/stream relation if you think about observables as APIs to interact with a stream.
Observables also allow us to operate over streams with a set of functional operators.
Your friendly neighbor:
RxJS
Reactive Extensions for JS
Are a set of libraries for composing asynchronous and event-based programs using observable sequences and fluent query operators that many of you already know by Array#extras in JavaScript
- RxJS github repo
Reactive Extensions
- Provides an API to work with streams
- Implements the observable primitive
Before going any further:
Basic RxJS implementation
RxJS operators
var source = Rx.Observable.range(0, 3)
.map(function (x) { return Rx.Observable.range(x, 3); })
.switch();
var subscription = source.subscribe(
function (x) {
console.log('Next: ' + x);
},
function (err) {
console.log('Error: ' + err);
},
function () {
console.log('Completed');
});switch
Convert an Observable that emits Observables into a single Observable that emits the items emitted by the most-recently-emitted of those Observables.
var source1 = Rx.Observable.of(1,2,3);
var source2 = Rx.Observable.of('foo', 'bar');
var source3 = Rx.Observable.of(4,5,6);
var merged = Rx.Observable.merge(source1, source2, source3);
var subscription = merged.subscribe(
function (x) { console.log('Next:' + x); },
function (err) { console.log('Error:' + err); },
function () { console.log('completed') }
);merge
Combine multiple Observables into one by merging their emissions.
var source = Rx.Observable.timer(0, 1000)
.takeUntil(Rx.Observable.timer(5000));
var subscription = source.subscribe(
function (x) { console.log('Next: ' + x); },
function (err) { console.log('Error: ' + err); },
function () { console.log('Completed'); });takeUntil
Discard any items emitted by an Observable after a second Observable emits an item or terminates.
var source = Rx.Observable.range(1, 5)
.takeWhile(x => x < 3);
var subscription = source.subscribe(
function (x) { console.log('Next: ' + x); },
function (err) { console.log('Error: ' + err); },
function () { console.log('Completed'); });takeWhile
Mirror items emitted by an Observable until a specified condition becomes false.
var source = Rx.Observable.range(1, 3)
.scan((acc, x) => acc + x);
var subscription = source.subscribe(
function (x) { console.log('Next: ' + x); },
function (err) { console.log('Error: ' + err); },
function () { console.log('Completed'); });scan
Apply a function to each item emitted by an Observable, sequentially, and emit each successive value.
var source = Rx.Observable.range(1, 3)
.mapTo(x => x + 10)
.startWith(5)
.scan((acc, x) => x(acc));
var subscription = source.subscribe(
function (x) { console.log('Next: ' + x); },
function (err) { console.log('Error: ' + err); },
function () { console.log('Completed'); });mapTo
Maps every value to the same value every time.
var source = Rx.Observable.range(1, 3)
.startWith(5)
.scan(
function (acc, x) {
return acc + x;
});
var subscription = source.subscribe(
function (x) { console.log('Next: ' + x); },
function (err) { console.log('Error: ' + err); },
function () { console.log('Completed'); });startWith
Emit a specified sequence of items before beginning to emit the items from the source Observable.
// Using a function
var source = Rx.Observable.range(1, 3)
.map(function (x, idx, obs) {
return x * x;
});
var subscription = source.subscribe(
function (x) { console.log('Next: ' + x); },
function (err) { console.log('Error: ' + err); },
function () { console.log('Completed'); });map
Transform the items emitted by an Observable by applying a function to each item.
var source = Rx.Observable.range(0, 5)
.filter(function (x, idx, obs) {
return x % 2 === 0;
});
var subscription = source.subscribe(
function (x) { console.log('Next:' + x); },
function (err) { console.log('Error:' + err); },
function () { console.log('Completed'); });filter
Emit only those items from an Observable that pass a predicate test.
var source = Rx.Observable.range(1, 3)
.reduce((acc, x) => acc * x)
var subscription = source.subscribe(
function (x) { console.log('Next: ' + x); },
function (err) { console.log('Error: ' + err); },
function () { console.log('Completed'); });reduce
Apply a function to each item emitted by an Observable, sequentially, and emit the final value.
var source1 = Rx.Observable.interval(100)
.map(function (i) { return 'First: ' + i; });
var source2 = Rx.Observable.interval(150)
.map(function (i) { return 'Second: ' + i; });
var source = source1.combineLatest(
source2,
function (s1, s2) { return s1 + ', ' + s2; }
).take(4);
var subscription = source.subscribe(
function (x) {
console.log('Next: ' + x.toString());
},
function (err) {
console.log('Error: ' + err);
},
function () {
console.log('Completed');
});combineLatest
When an item is emitted by either of two Observables, combine the latest item emitted by each Observable via a specified function and emit items based on the results of this function
References and further reading

Functional Reactive Programming
By Carlos Vega
Functional Reactive Programming
- 427
