The document discusses reactive programming with Observables and RxJS. It begins by explaining application goals of keeping applications responsive at all times and being resilient to failures. It then covers async JavaScript, promises versus observables, and the data model of streams. It introduces Observables and their creation, basic usage, and operators in RxJS. Finally, it provides a use case example of building a resilient web socket connection using Observables.
2. Globalcode – Open4education
Agenda
Application goals
Async JS
Promises vs. Observables
Data model - Streams
Basic usage
Observables
Creation from scratch
Quick recap
RxJS to the rescue
What is this
Creation helpers
Operators
“hot" vs. “cold"
Use case - Resilient web socket
3. Globalcode – Open4education
Application goals
Keep responsive all the times - React on load
Unacceptable halt while processing
Resilient - React on fail - Self recover
Reactive
Impossible to predict when process will be done
Advantage of Async
4. Globalcode – Open4education
Async JS
Levels of async computations
Time and latency become key issues
Simple applications “callback" is enough
But to scale … hard to maintain, hard to test
Async computation is hard to manage
7. Globalcode – Open4education
Promises vs. Observables
Both are built to solve async problems
(to avoid callback hell)
The idea of future values
Eventual results
Code scalability
8. Globalcode – Open4education
Promises vs. Observables
Fluent interface with notion of time and exposes the
method continually
Read-only view to a single future value
Success and fail semantics via .then() and .catch()
Not lazy, once started, it is on the way to being
resolved
Not cancellable, it will resolve or reject, only once
10. Globalcode – Open4education
Promises vs. Observables
“Streams” or collections
Any amount of data
Any amount of time
Lazy, by default. Just produce values when there
are subscribers
Can be cancelled, stop producing values
Objects that can inform other objects of the
changes they publish
11. 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”
12. Globalcode – Open4education
Data Model - Streams
Nothing more than a sequence of events/data over
time
Streams are immutable, data can just be changed
with another stream
Variables with the ability to react to changes
emitted from the data to a certain point
13. Globalcode – Open4education
Data Model - Streams
“With observables, anything is a stream
and, it is good”
Array Stream
MSFT [$44, $45, $46, $45] {$44.. $45…. $4…. $45}
NFLX [$95, $96, $97, $96, $101] {$95. $96…$97…. $96…}
14. Globalcode – Open4education
Observables
The most important concept
Wrap 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)
16. 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();
});
17. 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()
19. Globalcode – Open4education
What is this?
“RxJS is lodash for async” with Observables
Functional / reactive Programming with
Observables
Handle events, or any source, as stream collections
Many, many, many operators to manipulate sets
Decisions guided by performance
Contributors at Netflix, Google and Microsoft
21. Globalcode – Open4education
Can be retried / repeated
// retry three times on fail
Observable.retry(3);
// retry always on fail
Observable.retry();
// retry after 1,5s on fail
Observable.retryWhen(errors => errors.delay(1500));
// always repeat on complete
Observable.repeat();
// repeat twice
Observable.repeat(2);
22. Globalcode – Open4education
Can be combined / connected
// combine values whenever any emit
Observable.combineLatest(…Observables);
// emits all when all completes
Observable.forkJoin(…Observables);
// emit chunks when all at same index have emitted
Observable.zip(…Observables);
// parallel combination
Observable.merge(…Observables);
// serial combination
Observable.concat(…Observables);
// connect streams with merge strategy
Observable.mergeMap(() => Observable);
24. 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.
25. 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.
29. Globalcode – Open4education
Hot vs. Cold
Observables are “cold” by default
Cold 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).
30. Globalcode – Open4education
Use Case - Resilient Websocket
Connect to a web socket server
For each subscriber
Send subscription to server
Filter desired responses
When done, unsubscribe
Ideally, keep socket opened just while data is
required
31. Globalcode – Open4education
Use Case - Resilient Websocket
On connection fail
Keep state of all subscribers
Check when able to reconnect
Reconnect
Once reconnected, send subscriptions again
Keep consuming
32. Globalcode – Open4education
Use Case - Resilient Websocket
http://tdc-rxjs.herokuapp.com
https://github.com/feliperohdee/tdc-rxjs-demo
35. Globalcode – Open4education
Felipe Rohde
felipe@smallorange.co
facebook.com/feliperohdee
github.com/feliperohdee
https://www.npmjs.com/package/one-framework
Notas do Editor
Se vc n conhecem, provavelmente a chaordic conhece vcs
faz personalizações e produtos, emails, então td é super dimensionado
felizmente atingi um patamar pars seguir meu sonho
vim falar e uma tecnologia disruptiva, na qual, provavelmente, se vc trabalham, ou vierem a trabalhar em uma pequena startup de filmes, a netflix, vcs devem, ou deverão ser bem familiarizados
Um dos fatores mais importantes de qualquer aplicação é permanecer respondia durante todo o tempo. Isto significa q é inaceitável para uma aplicação travar enquanto processa I/O.
Ler do disco ou da rede é muito mais lento do que executar uma tarefa na CPU
Tendo em vista que, geralmente falando, as operações de IO (ler o disco ou da própria rede) são muito mais lentas do que instruções executadas na CPU. E que isto se aplica tanto no cliente como no servidor. A primeira solução para executar vários processos paralelo foram os callbacks, que emitem vários processos separados para executar tarefas longas.
Uma vez que a tarefa finaliza, a runtime do JS executa o callback com o resultado. O controle do programa não depende do programador (afinal, é impossível prever quando um processo vai completar), mas sim da runtime do JS. É aceitável para aplicações pequenas, porém praticamente impossível para aplicações que vão crescer. O que quero dizer é, tão logo vc precise conectar vários módulos, sua aplicação irá sofrer com callback hell.
Multiple issues
Nested functions
Welcome to promises in ES6
Promises - Provavelmente um passo na direção certa. A dificuldade de entendimento do código com Promises reduz dramaticamente. Mas Promises tem suas limitações, uma vez que são muito eficientes para se trabalhar com resultados q retornam uma única vez (ou um erro). Também são ineficientes para se trabalhar com eventos, fluxos constantes de dados como streams, ou resiliência de uma maneira simples, uma vez que não há semânticas para cancelamento de eventos, disposição, retentativas, repetições, …, Observables to the rescue
Ele nos traz os conceitos de Observer pattern e programação funcional / reativa junto. O Observer pattern é usado para prover um design aprovado baseado em produtores (Observables) e os consumidores (Observers ou Subscribers), que se inscrevem para receber eventos no decorres o tempo, o que oferece uma boa separação dos dois casos.
Mais ainda, conceitos de programação funcional, como códigos declarativos, estruturas de dados imutáveis, e combinação de métodos de uma forma fluente, para se dizer o mínimo. Permite que se escreva códigos expressivos e fáceis de entender como os dados irão se comportar. (bye bye callbacks e promises)
Se vc é familiarizado com programação funcional em JS, vc pode pensar em Observables e RXJS como o lodash a programação assíncrona.
RxJS introduz uma abrangente tipo estrutura de dados chamada stream
Streams não são nada mais que uma sequencia e eventos através do tempo. Streams podem ser usados para processar qualquer tipo de evento, como clicks de mouses, bytes originados da rede, enfim, qualquer tipo de IO.
Você pode pensar em streams como variáveis que possuem a capacidade de reagir a mudanças emitidas por outros eventos de um ponto a outro, e que podem sem interligados uns com os outros, criando uma única rede de streams. O que permite especificar um comportamento dinâmico de um dado de uma maneira declarativa. Em Observables, tudo é stream, e isto é bom.
Stream builder
120 micro performance tests
10 macro performance tests around common scenarios and bottlenecks