35
Globalcode – Open4education Node.js – Reactive Programming with Observables and RxJS Felipe Rohde

TDC2016SP - Trilha Node.Js

Embed Size (px)

Citation preview

Page 1: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

Node.js – Reactive Programming with Observables and RxJS

Felipe Rohde

Page 2: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

Agenda

Application goalsAsync JSPromises vs. Observables

Data model - StreamsBasic usageObservablesCreation from scratchQuick recap

RxJS to the rescueWhat is thisCreation helpersOperators“hot" vs. “cold" Use case - Resilient web socket

Page 3: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

Application goals

Keep responsive all the times - React on loadUnacceptable halt while processingResilient - React on fail - Self recoverReactiveImpossible to predict when process will be doneAdvantage of Async

Page 4: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

Async JS

Levels of async computationsTime and latency become key issuesSimple applications “callback" is enoughBut to scale … hard to maintain, hard to testAsync computation is hard to manage

Page 5: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

Callback Hell

makeHttpCall('/items', items => { for (itemId of items) { makeHttpCall(`/items/${itemId}/info`, itemInfo => { makeHttpCall(`/items/${itemInfo.pic}`, img => { showImg(img); }); }); }});

Page 6: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

Async JS

Callbacks (Callback Hell)Promises (ES6 Spec)GeneratorsAsync / AwaitObservables (ES7 Spec)

Page 7: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

Promises vs. Observables

Both are built to solve async problems (to avoid callback hell)The idea of future valuesEventual resultsCode scalability

Page 8: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

Promises vs. Observables

Fluent interface with notion of time and exposes the method continuallyRead-only view to a single future valueSuccess and fail semantics via .then() and .catch()Not lazy, once started, it is on the way to being resolvedNot cancellable, it will resolve or reject, only once

Page 9: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

Promises vs. Observables

makeHttpCall('/items') .then(itemId => makeHttpCall(`/items/${itemId}/info`)) .then(itemInfo => makeHttpCall(`/items/${itemInfo}.pic}`)) .then(showImg);

Page 10: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

Promises vs. Observables

“Streams” or collectionsAny amount of dataAny amount of timeLazy, by default. Just produce values when there are subscribersCan be cancelled, stop producing valuesObjects that can inform other objects of the changes they publish

Page 11: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

Promises vs. Observables

Single return value Multiple return values

Pull / Sync / Interactive Object Iterables (Array, Set, Map, Object)

Push / Async / Reactive Promise Observable

“Observables, returns 0 - ∞ values between now and the end of time”

Page 12: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

Data Model - Streams

Nothing more than a sequence of events/data over timeStreams are immutable, data can just be changed with another streamVariables with the ability to react to changes emitted from the data to a certain point

Page 13: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

Data Model - Streams

“With observables, anything is a streamand, it is good”

Array Stream

MSFT [$44, $45, $46, $45] {$44.. $45…. $4…. $45}

NFLX [$95, $96, $97, $96, $101] {$95. $96…$97…. $96…}

Page 14: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

Observables

The most important conceptWrap a piece of data and decorate it with stream-like qualities (string, numbers, sets, collections, websocket, requests, …any)The most simple is Observable.of(anything)

Page 15: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

Basic Usage

Promise Observable

.then(valueFn) .subscribe(valueFn, errorFn, completeFn)

.catch(err => Promise.resolve(err)) .catch(err => Observable.of(err))

.finally(() => console.log(‘done’)) .finally(() => console.log(‘done’))

Not cancellable let sub = observable.subscribe(valueFn)sub.unsubscribe();

Page 16: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

Creation from scratch

Promise Observable

new Promise((resolve, reject) => { asyncFn((err, data) => { if (err) { return reject(err); }

resolve(data); });});

new Observable(subscriber => { asyncFn((err, data) => { if (err) { return subscriber.error(err); }

subscriber.next(data); subscriber.complete(); });

return () => cancelAnything();});

Page 17: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

Quick recap

Set of any amount of things over any amount of time.Values are pushed, to subscribers, via nextFn.Errors are pushed to errFn.On complete completeFn is called.By default, they are lazy, nothing is produced until at least one subscriber.

let sub = observable.subscribe(nextFn, errFn, completeFn)sub.unsubscribe()

Page 18: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

RxJS to the rescue

Page 19: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

What is this?

“RxJS is lodash for async” with ObservablesFunctional / reactive Programming with ObservablesHandle events, or any source, as stream collectionsMany, many, many operators to manipulate setsDecisions guided by performanceContributors at Netflix, Google and Microsoft

Page 20: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

Creation helpers

Observable.of(…values);Observable.from(typeof promise / iterable)Observable.fromEvent(item, eventName)Observable.fromPromise(PromiseLike)Observable.fromCallback((callback) => ..);Observable.fromNodeCallback((err, callback) => ..);Observable.interval(number);range(number, number);Observable…

Page 21: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

Can be retried / repeated

// retry three times on failObservable.retry(3);

// retry always on failObservable.retry();

// retry after 1,5s on failObservable.retryWhen(errors => errors.delay(1500));

// always repeat on completeObservable.repeat();

// repeat twiceObservable.repeat(2);

Page 22: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

Can be combined / connected// combine values whenever any emitObservable.combineLatest(…Observables);

// emits all when all completesObservable.forkJoin(…Observables);

// emit chunks when all at same index have emittedObservable.zip(…Observables);

// parallel combinationObservable.merge(…Observables);

// serial combinationObservable.concat(…Observables);

// connect streams with merge strategyObservable.mergeMap(() => Observable);

Page 23: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

Operators - The real power

Page 24: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

Operators - What is this

Methods to compose Observables and create new ones.

let mapped = Observable.interval(1000) .filter(value => value % 2) .map(value => value * 3) .take(3);

Mapped is a new Observable that when subscribed, subscribes to interval observable and theirs operators.

Page 25: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

Operators - How they work

Operators pass each value from one to the next, before process next set’s value, like lazy evaluation.Different from array operators, which process whole array, creating intermediates for each step.

Page 26: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

Arrays way

Items.filter(notRed).map(toScale).take(3);

Page 27: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

Operators way

Items.filter(notRed).map(toScale).take(3);

Page 28: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

Some operators

Basicmap, reduce, filter, first, last, toArray, take, skip, scan, repeat, max, min,

expand, forEach, do, pluck, …

Merging and joiningmerge, concat, mergeMap, concatMap,

switchMap, forkJoin, race, combineLatest, zip, …

Splitting and grouping groupBy, window, partition, pairwise, withLatestFrom, …

Buffer and backpressure Buffer, throttle, debounce, sample, distinctUntilChanged, …

Fail tolerance and redundancy strategies catch, retry, retryWhen, onErrorResumeNext, publishReplay, …

Page 29: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

Hot vs. Cold

Observables are “cold” by defaultCold observables create a new producer each time a subscriber subscribes to them.Hot observables share a single producer with every subscriber. And optionally can emit values without any subscriber (Like mouse events).

Page 30: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

Use Case - Resilient Websocket

Connect to a web socket serverFor each subscriber

Send subscription to serverFilter desired responsesWhen done, unsubscribe

Ideally, keep socket opened just while data is required

Page 31: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

Use Case - Resilient Websocket

On connection failKeep state of all subscribersCheck when able to reconnectReconnectOnce reconnected, send subscriptions againKeep consuming

Page 32: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

Use Case - Resilient Websocket

http://tdc-rxjs.herokuapp.comhttps://github.com/feliperohdee/tdc-rxjs-demo

Page 33: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

Use case - Websocket Observable

Page 34: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

Use case - Resilient web socket

Page 35: TDC2016SP - Trilha Node.Js

Globalcode – Open4education

Felipe Rohde

[email protected]/feliperohdee

github.com/feliperohdeehttps://www.npmjs.com/package/one-framework