RxJS Typescript Workshop

Reactive programming, Event Sourcing & CQRS in the frontend


David Sherman
Frontend Dev @ Essent
Henk Bakker
Frontend Dev @ Essent
Making the browser do stuff it wasn't made for
Reactive programming is programming with asynchronous data streams.
"What is Reactive Programming?"
Reactive programming isn't new!
Excel anyone?
Storing all the changes (events) to the system, rather than just its current state.
"What is Event Sourcing?"
Event sourcing

An architecture style that separates read operations from write operations
"What is CQRS?"
* Command Query Responsibility Segregation
CQRS

Back to the browser
Traditionally we are using Promises for async
Promises

Types of async in modern web apps
- DOM events
- Animations
- AJAX
- WebSockets
- ServerSendEvents
Promises only really make sense for one of these
-
DOM events
-
0-N values
-
-
Animations
-
cancelable
-
-
AJAX
-
1 value
-
-
WebSockets
-
0-N values
-
-
ServerSendEvents
-
0-N values
-
... except when they don't
- Single page applications commonly prepare data via AJAX for each view shown
- When the view changes, the next view probably doesn't care about the previous view's data
- Fortunately, XHRs can be aborted!
- .. but promise-based AJAX implementations cannot be aborted, because promises cannot be cancelled
So how do we go from Promises to Observables?
Observable
- "Streams" or sets
- Of any number of things
- Over any amount of time
- Lazy
- Observables will not generate values via an underlying producer until they're subscribed to.
- Can be "unsubscribed" from.
- This means the underlying producer can be told to stop and even tear down

Observable
+
Iterator pattern
=
Observer pattern
Both Promises and Observables are built to solve problems around async
(to avoid "callback hell")
fs.readdir(source, function (err, files) {
if (err) {
console.log('Error finding files: ' + err)
} else {
files.forEach(function (filename, fileIndex) {
console.log(filename)
gm(source + filename).size(function (err, values) {
if (err) {
console.log('Error identifying file size: ' + err)
} else {
console.log(filename + ' : ' + values)
aspect = (values.width / values.height)
widths.forEach(function (width, widthIndex) {
height = Math.round(width / aspect)
console.log('resizing ' + filename + 'to ' + height + 'x' + height)
this.resize(width, height).write(dest + 'w' + width + '_' + filename, function(err) {
if (err) console.log('Error writing file: ' + err)
})
}.bind(this))
}
})
})
}
})
Operators
Observables
Schedulers
+
+
=
RxJS
What are these "operators?"
Operators are functions that you can use on Observables that allow you to change the original observable in some manner and return a new observable
JS Array
RxJS Operator
const r = [1, 2, 3, 4, 5, 6]
.map(x => x * x)
.filter(y => y % 2 == 0);
console.log(r);
// log: [4, 16, 36]
from([1, 2, 3, 4, 5, 6]).pipe(
map(x => x * x)
filter(y => y % 2 == 0)
).subscribe(r => console.log(r));
// log: 4
// log: 16
// log: 36

"RxJS is Lodash for async"
What are we building

Before we dive into code
Workshop Time
Let's code
Hot Observables
Ben Lesh about Hot vs Cold observables
Observables are "cold" by default
"Cold" observables create a new producer each time a consumer subscribes to them
"Hot" observables share a single producer with every consumer that subscribes to them
Learn more about RxJS
RxJS Typescript Workshop
By Henk
RxJS Typescript Workshop
Reactive programming, Event Sourcing & CQRS in the frontend
- 470