I presented a Session on Rx.js at DevNation this year. My goal was to impress upon the audience how Observables can be interpreted as a collection-in-time. This analogy was very well described by @jhusain his Async Javascript at Netflix talk that initially got me excited about Reactive Functional programming. My contribution to this idea is to present it in a visual way.
To visualize both a "regular" collection, as well as a collection-in-time, I used the d3.js library to visually present a collection of javascript objects that each represent a shape with a given size, color, and shape-type. In my presentation I embedded these visualizations using as Codepens, which I’ve included in this blog post below.
The slides from my presentation are available at:
A Collection
Here is the visualization of a Collection. With a "regular" collection we can get a reference to every object in the collection at any given point in time. Go ahead, "grab" a shape with your mouse!
See the Pen Collection | Iden by Brian Leathem (@bleathem) on CodePen.
An Observable
And here we have the visualization of an Observable as a Collection-in-time. An Observable is different from a "regular" collection in that we cannot grab a reference to every object at any given point in time. The objects stream past us as time progresses.
See the Pen Observable by Brian Leathem (@bleathem) on CodePen.
Reactive Extensions
In the session I then proceed to use these visualizations as basis for describing some of the tools we use for manipulating Collections/Observables:
Map
With the map
function we can operate on each item in the collection. In our example mapping function we map each shape into a new shape of the same size, but of type square and color green.
.map(function(x) {
return {
id: x.id
, color: 'green'
, size: x.size
, type: 'square'
};
});
Collection map
Here we have the above map
function applied to a "regular" Collection:
See the Pen Operating on a Collection by Brian Leathem (@bleathem) on CodePen.
Observable map
The above map
function applied to an Observable:
See the Pen Map an Observable by Brian Leathem (@bleathem) on CodePen.
MergeAll
The mergeAll
function is used to "flatten" a 2-dimensional collection into a 1-dimensional collection. In this code sample we map each shape into a pair of shapes which we return as an array. The resulting "array of arrays" is then passed to the mergeAll
function where it is flattened.
.map(function(x) {
var y = _.clone(x);
y.id = y.id + 80;
y.color = 'green';
var z = _.clone(x);
y.size = y.size / 1.5;
z.size = z.size / 1.5;
return [y, z];
})
.mergeAll();
Nested Collections
This visualization shows the above mapping without the mergeAll
applied. Notice how the resulting collection consists of object pairs. We do not have a flat collection. Try to grab one of the shapes with your mouse and see for yourself!
See the Pen Map a nested Collection by Brian Leathem (@bleathem) on CodePen.
Nested Collections mergeAll
With the mergeAll
function applied to the Nested collection we now have a flattened collection, which we can continue to operate on with our tool set.
See the Pen MergeAll a Collection by Brian Leathem (@bleathem) on CodePen.
Observable mergeAll
The mergeAll
function applied to a 2-dimensional Observable.
See the Pen MergeAll an Observable by Brian Leathem (@bleathem) on CodePen.
FlatMap
It turns out the map
→ mergeAll
combination is a pattern we apply so often that we created the flatMap
function as a shorthand. We can then rewrite the above transformation as:
.flatMap(function(x) {
var y = _.clone(x);
y.id = y.id + 80;
y.color = 'green';
var z = _.clone(x);
y.size = y.size / 1.5;
z.size = z.size / 1.5;
return [y, z];
});
Reduce
A common use case for analyzing collections is the reduce
function, where one iterates over a collection and "accumulates" a value for each object in the collection. In this code sample we are accumulating the size of each shape, and using that to create a new shape of the accumulated size.
var outputData = inputData
.reduce(function(acc, x) {
return {
id: x.id
, color: 'green'
, size: acc.size + x.size
, type: 'square'
};
}, {size: 0});
Collection reduce
The above reduce function applied to a collection:
See the Pen Reduce a Collection by Brian Leathem (@bleathem) on CodePen.
Observable reduce
The reduce
function applied to an Observable:
Note
|
You will want to click the |
See the Pen Reduce an Observable by Brian Leathem (@bleathem) on CodePen.
Zip
The last function we will look at is the zip
function which is used to combine many Observables into a single observable. It accomplishes this by taking each Observable as a parameter, followed by a function that is used to "combine" the object retrieved from each Observable.
In the following code sample we combine our shapes by creating a new shape with the color of the first shape, but the size and type of the 2nd shape.
var outputData = Rx.Observable.zip(
input1Data,
input2Data,
function(x1, x2) {
return {
id: x1.id
, color: x1.color
, size: x2.size
, type: x2.type
};
});
Observable zip
See the Pen Zip an Observable by Brian Leathem (@bleathem) on CodePen.
The rest of the talk
In the remaining slides I discuss creating and subscribing to Observables, and went through a number of use cases and examples. I ended with a preview and brief code walk-through of the Red Hat Summit Middleware keynote demo, that I wrote using Rx.js. But that is a topic for another post.
The slides are available at:
Share this post
Twitter
Google+
Facebook
Reddit
LinkedIn
StumbleUpon
Pinterest
Email