Slide 1

Slide 1 text

Intro RX Stream all the things

Slide 2

Slide 2 text

Mark van straten @markvanstraten Q42

Slide 3

Slide 3 text

“RX is a library for composing asynchronous and event-based programs by using observable sequences”

Slide 4

Slide 4 text

Value Promise Enumerable ????

Slide 5

Slide 5 text

Value Promise Enumerable Observable (Subject/Observer is Dual to Iterator - Erik Meijer - http://csl.stanford.edu/~christos/pldi2010.fit/meijer.duality.pdf)

Slide 6

Slide 6 text

A stream of future events is an Observable Listening to an observable is a Subscription State changes on an observable are done using Operators Concurrency is managed using Schedulers

Slide 7

Slide 7 text

Promise { onResolved, onRejected } Observable { onNext, onError, onCompleted }

Slide 8

Slide 8 text

SHOW ME CODE

Slide 9

Slide 9 text

UI Interaction function onDoubleClick(target, callback) { let clicks = 0; let self = this; return target.on('click', () => { clicks++; if(clicks == 1) { setTimeout(() => { if(clicks === 2) { callback.call(self); } clicks = 0; }, 300); } }); const target = document.querySelector('body'); onDoubleClick(target, () => console.log(‘got doubleClick’) const target = document.querySelector('body'); const clickStream = Rx.Observable.fromEvent(target, 'click'); clickStream .buffer(clickStream.debounce(300)) .map(list => list.length) .filter(x => x == 2) .subscribe(doubleClick => console.log('got doubleClick'));

Slide 10

Slide 10 text

API call retry logic // using observables function getUser(userId) { const getUserDetailsFallbacks = [ getUserFromServer(userId), getUserFromCache(userId), getEmptyUserObject(userId), ]; return Rx.Observable .catch(getUserDetailsFallbacks) .toPromise(); // optional } // using promises function getUser(userId) { return getUserFromServer(userId) .catch(err => getUserFromCache(userId) .catch(err => getEmptyUserObject(userId)) ); }

Slide 11

Slide 11 text

REAL LIFE EXAMPLE

Slide 12

Slide 12 text

I want to publish question(s) and retrieve my answer. If the answer is not in time throw an error.

Slide 13

Slide 13 text

Match response to request const allAnswersStream = redis.subscribe(‘answers:*’) .map(parseAnswer); function getAnswerForQuestion(q) { const answerStream = allAnswersStream .filter(a => a.id === q.id); return redis.publish(‘question:${q.id}’,q) .zip(answerStream) .take(1) /* only need one answer */ .timeout(2 * 1000) /* ms */ .map(qa => qa[1]);//only need the answer }

Slide 14

Slide 14 text

No content

Slide 15

Slide 15 text

OMG THE DOCUMENTATION

Slide 16

Slide 16 text

“transform the items emitted by an Observable into Observables, then flatten the emissions from those into a single Observable” Also known as flatMap() (http://reactivex.io/documentation/operators/flatmap.html)

Slide 17

Slide 17 text

No content

Slide 18

Slide 18 text

A LOT of operators (http://reactivex.io/documentation/operators.html)

Slide 19

Slide 19 text

Start with these ● map ● filter ● scan ● mergeMap ● switchMap ● combineLatest ● concat ● do

Slide 20

Slide 20 text

Find your RX Operator http://reactivex.io/rxjs/

Slide 21

Slide 21 text

No content

Slide 22

Slide 22 text

TESTING

Slide 23

Slide 23 text

Seen this? describe('MyService', function() { // ... setup stuff it('Retrieves user details', function(done) { // increased timeout because getUser sometimes takes a long time to complete this.timeout(5000); const promise = service.getUser(1) .then(user => { expect(user).to.not.be.null; }); expect(promise).to. eventually.be.fulfilled.and.notify(done); }); });

Slide 24

Slide 24 text

RX lets you do async in virtual time for testing

Slide 25

Slide 25 text

const scheduler = new Rx.TestScheduler(); const getUserFromServerStream = scheduler.createColdObservable( onNext(100, ({ id: 1, name: 'myUser' })), onCompleted(110) ); mocha.stub('getUserFromServer').returns(getUserFromServerStream); const results = scheduler.startScheduler( () => getUser(1) ); console.log(results.messages) // [0]=onNext(100, ({ id: 1, name: 'myUser' }))), [1]=onComplete(110)

Slide 26

Slide 26 text

PITFALLS

Slide 27

Slide 27 text

Most observables are lazy (cold) and only start when subscribed() to

Slide 28

Slide 28 text

Observables might never complete. Use take(x) for clarity

Slide 29

Slide 29 text

It’s easy to interleave Promises in Rx Use defer(() => myPromise()) to make them lazy

Slide 30

Slide 30 text

Multiple subscribe() calls will (default) create their own observable. Use share() to make these multicast compatible.

Slide 31

Slide 31 text

TAKEAWAYS

Slide 32

Slide 32 text

Rx is a complex tool for reducing cognitive load when talking about the complex problem called asynchronicity

Slide 33

Slide 33 text

Reference material RxJS 5 Thinking Reactively - Ben Lesh https://www.youtube.com/watch?v=3LKMwkuK0ZE http://reactivex.io http://rxmarbles.com/