SlideShare uma empresa Scribd logo
1 de 93
Baixar para ler offline
Rx.js
making async programming simpler
About me
Mostovenko Alexander
Python developer at
Writing mostly in python and coffeescript.
Love FP stuff.
Traveling, snowboarding, cycling.
https://twitter.com/MostovenkoA
https://github.com/AlexMost
Why Rx.js and not another FRP lib?
● Implemented in a lot of languages
(.NET, Java, Ruby, Python, Clojure, Scala,
Haskell, Objective-C).
● Has a huge amount of docs and examples.
● Why not?
Asynchronous code
Async code in javascript
● Some computation with delayed result.
(data fetch, animations, DOM operations)
● Reacting to events (event handlers)
Sync vs Async dataflow
Synchronous dataflow
Synchronous dataflow
In
Synchronous dataflow
In
1
Synchronous dataflow
In
1
2
Synchronous dataflow
In
1
2
...
Synchronous dataflow
In
1
2
Out
...
Asynchronous dataflow
time
Actions
Asynchronous dataflow (autocomplete)
time
Actions
keyup
Asynchronous dataflow (autocomplete)
time
Actions
keyup
per 2 seconds
Asynchronous dataflow (autocomplete)
time
Actions
keyup
per 2 seconds
ajax request
Asynchronous dataflow (autocomplete)
time
Actions
keyup
per 2 seconds
ajax request
ajax response
Asynchronous dataflow (autocomplete)
time
Actions
keyup
per 2 seconds
ajax request
ajax response
show suggest
Asynchronous dataflow (autocomplete)
time
Actions
keyup
per 2 seconds
ajax request
ajax response
show suggest
Asynchronous dataflow (autocomplete)
time
Actions
keyup
per 2 seconds
ajax request
ajax response
show suggest
Ooooops
Problems with async code
1. How to manage async flow in code?
2. How to handle errors?
3. How to compose?
Callbacks
● Event notification
● Manage control flow
Callbacks
● Event notification - Yes
● Manage control flow - Nooooooooooo
Callback hell
async_func1(function(err, data){
async_func2(function(err, data){
async_func3(function(err, data){
async_func4(function(err, data){
});
});
});
});
Callback hell yeah !!!
async_func1(function(err, data){
if (!err) {
async_func2(function(err, data){
if (!err) {
async_func3(function(err, data){
if (!err) {
async_func4(function(err, data){
});
} else {
log(err);
}
});
} else {
log(err);
}
});
} else {
log(err);
}
});
Callback hell yeah !!!
async_func1(function(err, data){
if (!err) {
async_func2(function(err, data){
if (!err) {
async_func3(function(err, data){
if (!err) {
async_func4(function(err, data){
});
} else {
log(err);
}
});
} else {
log(err);
}
});
} else {
log(err);
}
});
UNREADABLE !!!
UNMANAGABLE !!!
UNTESTABLE !!!
UNCOMPOSABLE !!!
PIECE OF ….
CODE
Monad
A monad is just a monoid in the category of
endofunctors
Callback vs Black hole
some_async_func(function(err, result) {
// ... looks like we are in trap
another_wonderful_func(function(err, result){
// ... you are in trap
});
});
Callback vs Black Hole
1. No return value (undefined)
Callback vs Black Hole
1. No return value (undefined)
2. One way ticket (callback hell)
How about Promise?
Promise
var promise = new Promise((resolve, reject) => {
// ... some async staff
});
promise.then(
(result) => {},
(error) => {}
)
Promise
1. Step forward from callbacks for control flow
managing
2. Error handling
Why we should look at Observable?
1. Promise represents only single value.
2. How to cancel?
3. Lazy execution.
4. We can work with Observable as easy as with
promise.
Promise is Observable only with a single value
Observable
The Observable object represents a push
based collection.
Observable
var source = Rx.Observable.create((observer) =>
// some async operation
observer.onNext(data)
// or ..
observer.onError(data)
// or ..
observer.onCompleted(data)
);
source.subscribe(
(data) => {}
(err) => {}
)
Observlable vs promise example
var source = Rx.Observable.create((observer) => {
setTimeout(() => {
console.log("observable timeout hit");
observer.onNext(25);
}, 500);
console.log('observable started')});
source.subscribe(x => console.log(`observable value ${x}`));
Observable
> observable started
> observable timeout hit
> observable value 25
Observlable vs promise example
var promise = new Promise((resolve) => {
setTimeout(() => {
console.log("promise timeout hit");
resolve(25);
}, 500);
console.log("promise started");});
promise.then(x => console.log(`promise value ${x}`));
Promise
> promise started
> promise timeout hit
> promise value 25
Lazy execution
var source = Rx.Observable.create((observer) => {
setTimeout(() => {
console.log("observable timeout hit");
observer.onNext(25);
}, 500);
console.log('observable started')});
// source.subscribe(x => console.log(`observable value ${x}`));
>
Observable can be canceled
var source = Rx.Observable.create((observer) => {
var id = setTimeout(() => {
console.log("observable timeout hit");
observer.onNext(25);
}, 500);
console.log('observable started');
return () => {
console.log("dispose called")
clearTimeout(id);}
});
var disposable = source.subscribe(
x => console.log(`observable value ${x}`));
setTimeout(() => disposable.dispose(), 100)
> observable started
> dispose called
Asynchronous programming landscape
multiple
values
single
value
sync async
a = f(x) a = f(x).then(...)
collection = [1, 2, 3]
a = collection
.filter((v) => v > 2)
Promise
Array
Sync value
?
Asynchronous programming landscape
multiple
values
single
value
sync async
a = f(x) a = f(x).then(...)
collection = [1, 2, 3]
a = collection
.filter((v) => v > 2)
move = Rx.Observable.fromEvent(document, 'mousemove')
my_moves = move
.filter((ev) => ev.clientX > 100)
my_moves.subscribe(...)
Promise
Array
value
Observable
How to create Observable
● Observable.create
● Observable.fromEvent
● Observable.fromNodeCallback
● Observable.fromArray
● Observable.fromPromise
Drag & Drop example
What if i told you ….
That mouse move event is an array and you
can map, filter over it?
var dragTarget = document.getElementById('dragTarget');
// Get the three major events collections
var mouseup = Rx.DOM.fromEvent(dragTarget, 'mouseup');
var mousemove = Rx.DOM.fromEvent(document, 'mousemove');
var mousedown = Rx.DOM.fromEvent(dragTarget, 'mousedown');
var mousedrag = mousedown.flatMap(({offsetX, offsetY}) => {
return mousemove
.map(({clientX: x, clientY: y}) => {
return {left: x - offsetX, top: y - offsetY}})
.takeUntil(mouseup)
});
var subscription = mousedrag.subscribe((pos) => {
dragTarget.style.top = pos.top + 'px';
dragTarget.style.left = pos.left + 'px';
});
var dragTarget = document.getElementById('dragTarget');
// Get the three major events collections
var mouseup = Rx.DOM.fromEvent(dragTarget, 'mouseup');
var mousemove = Rx.DOM.fromEvent(document, 'mousemove');
var mousedown = Rx.DOM.fromEvent(dragTarget, 'mousedown');
var mousedrag = mousedown.flatMap(({offsetX, offsetY}) => {
return mousemove
.map(({clientX: x, clientY: y}) => {
return {left: x - offsetX, top: y - offsetY}})
.takeUntil(mouseup)
});
var subscription = mousedrag.subscribe((pos) => {
dragTarget.style.top = pos.top + 'px';
dragTarget.style.left = pos.left + 'px';
});
Create observable collections
from DOM events
var dragTarget = document.getElementById('dragTarget');
// Get the three major events collections
var mouseup = Rx.DOM.fromEvent(dragTarget, 'mouseup');
var mousemove = Rx.DOM.fromEvent(document, 'mousemove');
var mousedown = Rx.DOM.fromEvent(dragTarget, 'mousedown');
var mousedrag = mousedown.flatMap(({offsetX, offsetY}) => {
return mousemove
.map(({clientX: x, clientY: y}) => {
return {left: x - offsetX, top: y - offsetY}})
.takeUntil(mouseup)
});
var subscription = mousedrag.subscribe((pos) => {
dragTarget.style.top = pos.top + 'px';
dragTarget.style.left = pos.left + 'px';
});
Using power of Rx, combine
existing event streams to produce
mouse drag event collection
var dragTarget = document.getElementById('dragTarget');
// Get the three major events collections
var mouseup = Rx.DOM.fromEvent(dragTarget, 'mouseup');
var mousemove = Rx.DOM.fromEvent(document, 'mousemove');
var mousedown = Rx.DOM.fromEvent(dragTarget, 'mousedown');
var mousedrag = mousedown.flatMap(({offsetX, offsetY}) => {
return mousemove
.map(({clientX: x, clientY: y}) => {
return {left: x - offsetX, top: y - offsetY}})
.takeUntil(mouseup)
});
var subscription = mousedrag.subscribe((pos) => {
dragTarget.style.top = pos.top + 'px';
dragTarget.style.left = pos.left + 'px';
});
Subscribe on mouse drag events,
updating top and left attributes
Observable are first class events
Can be:
- passed as a parameter
- returned from a function
- assigned to a variable
Some common basic operations
map
filter
reduce
zip
merge
flatMap
...
https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/observable.md
map
http://rxmarbles.com/#map
filter
http://rxmarbles.com/#filter
var mousedrag_in_area = mousedrag.filter(({top, left}) => {
return top <= 200 && left <= 200
});
var subscription = mousedrag_in_area.subscribe((pos) => {
dragTarget.style.top = pos.top + 'px';
dragTarget.style.left = pos.left + 'px';
});
let’s filter drag area
delay
http://rxmarbles.com/#delay
let’s create slow mouse drag
var slow_mousedrag = mousedrag.delay(700)
var subscription = slow_mousedrag.subscribe((pos) => {
dragTarget.style.top = pos.top + 'px';
dragTarget.style.left = pos.left + 'px';
});
reduce
http://rxmarbles.com/#reduce
let’s record our drag path
var drag_path = mousedrag
.takeUntil(mouseup)
.reduce(((a, b) => a + `${b.top} ${b.left};`), "")
drag_path.subscribe((path) => pathTarget.innerHTML = path)
flatMap
flatMap
var mousedrag = mousedown.flatMap(({offsetX, offsetY}) => {
return mousemove
.map(({clientX: x, clientY: y}) => {
return {left: x - offsetX, top: y - offsetY}})
.takeUntil(mouseup)
});
flatMap
var mousedrag = mousedown.flatMap(({offsetX, offsetY}) => {
return mousemove
.map(({clientX: x, clientY: y}) => {
return {left: x - offsetX, top: y - offsetY}})
.takeUntil(mouseup)
});
Outer stream
flatMap
var mousedrag = mousedown.flatMap(({offsetX, offsetY}) => {
return mousemove
.map(({clientX: x, clientY: y}) => {
return {left: x - offsetX, top: y - offsetY}})
.takeUntil(mouseup)
});
value as a stream
merge
http://rxmarbles.com/#merge
merge
var btnTarget = document.getElementById('okbtn');
var buttonClicks = Rx.DOM.fromEvent(btnTarget, 'click');
var move_to_100 = buttonClicks.map(() => {return {left: 100, top: 100}});
var change_position = Rx.Observable.merge(mousedrag, move_to_100)
change_position.subscribe((pos) => {
dragTarget.style.top = pos.top + 'px';
dragTarget.style.left = pos.left + 'px';
});
merge
var btnTarget = document.getElementById('okbtn');
var buttonClicks = Rx.DOM.fromEvent(btnTarget, 'click');
var move_to_100 = buttonClicks.map(() => {return {left: 100, top: 100}});
var change_position = Rx.Observable.merge(mousedrag, move_to_100)
change_position.subscribe((pos) => {
dragTarget.style.top = pos.top + 'px';
dragTarget.style.left = pos.left + 'px';
});
new stream
And a lot of other methods ….
● amb
● and
● asObservable
● average
● buffer
● bufferWithCount
● bufferWithTime
● bufferWithTimeOrCount
● catch | catchError
● combineLatest
● concat
● concatAll
● concatMap
● concatMapObserver
● connect
● includes
● controlled
● count
● debounce
● debounceWithSelector
● defaultIfEmpty
● delay
● delaySubscription
● delayWithSelector
● dematerialize
● distinct
● distinctUntilChanged
● do
● doOnNext
● doOnError
● doOnCompleted
● doWhile
● elementAt
● elementAtOrDefault
● every
● expand
● extend
● filter
● find
● findIndex
● first
● firstOrDefault
● flatMap
● flatMapObserver
● flatMapLatest
● forkJoin
● groupBy
● groupByUntil
● groupJoin
● ignoreElements
● indexOf
● isEmpty
● join
● jortSort
● jortSortUntil
● last
● lastOrDefault
● merge
● mergeAll
● min
● minBy
● multicast
● observeOn
● onErrorResumeNext
● pairwise
● partition
● pausable
● pausableBuffered
● pluck
● publish
● publishLast
● publishValue
● share
● shareReplay
● shareValue
● refCount
● reduce
● repeat
● replay
● retry
● retryWhen
● sample
● scan
● select
● selectConcat
● selectConcatObserver
● selectMany
● selectManyObserver
● selectSwitch
● sequenceEqual
● single
● singleOrDefault
● singleInstance
● skip
● skipLast
● skipLastWithTime
● skipUntil
https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/observable.md
Testing with time machine
Rx.TestScheduler
var mult_stream = some_stream.debounce(100).map((n) => n * 2)
assertRxActions(
mult_stream,
[
[100, {value: 20}],
[200, {value: 40}]
],
[
[200, {value: 80}]
],
(result) => assertTrue(result)
)
var mult_stream = some_stream.debounce(100).map((n) => n * 2)
assertRxActions(
mult_stream,
[
[100, {value: 20}],
[200, {value: 40}]
],
[
[200, {value: 80}]
],
(result) => assertTrue(result)
)
stream to test
var mult_stream = some_stream.debounce(100).map((n) => n * 2)
assertRxActions(
mult_stream,
[
[100, {value: 20}],
[200, {value: 40}]
],
[
[200, {value: 80}]
],
(result) => assertTrue(result)
)
Input stream messages
var mult_stream = some_stream.debounce(100).map((n) => n * 2)
assertRxActions(
mult_stream,
[
[100, {value: 20}],
[200, {value: 40}]
],
[
[200, {value: 80}]
],
(result) => assertTrue(result)
)
time
var mult_stream = some_stream.debounce(100).map((n) => n * 2)
assertRxActions(
mult_stream,
[
[100, {value: 20}],
[200, {value: 40}]
],
[
[200, {value: 80}]
],
(result) => assertTrue(result)
)
Expected result at time
var mult_stream = some_stream.debounce(100).map((n) => n * 2)
assertRxActions(
mult_stream,
[
[100, {value: 20}],
[200, {value: 40}]
],
[
[200, {value: 80}]
],
(result) => assertTrue(result)
)
callback for assert
React ?
● Rx-React
● RxReact
● cycle-react
● React RxJS Autocomplete
● React RxJS TODO MVC
● Rx TODO MVC
● React RxJS Router
● React + RxJS + Angular 2.0 di.js TODO MVC
● React + RxJS Reactive Cube
● Real-Time with React + RxJS + Meteor
● React + RxJS Flow
● Reactive Widgets
● React RxJS Infinite Scroll
Flux ?
● Rx-Flux
● ReactiveFlux
● Thundercats.js
● Flurx
● RR
RxReact
some info - http://habrahabr.ru/post/251835/
repo with demos - https://github.com/AlexMost/RxReact
RxReact (simple click count)
Simple case
demo - http://alexmost.github.io/RxReact/hello_world/public/index.html
code - https://github.com/AlexMost/RxReact/tree/master/hello_world/hello_world
dispatchActions = (view, eventStream, store) ->
incrementClickStream = eventStream
.filter(({action}) -> action is "increment_click_count")
.do(-> store.incrementClicksCount())
Rx.Observable.merge(
incrementClickStream
# some more actions here for updating view ...
).subscribe(
-> view.setProps getViewState(store)
(err) ->
console.error? err)
RxReact (simple click count)
dispatchActions = (view, eventStream, store) ->
incrementClickStream = eventStream
.filter(({action}) -> action is "increment_click_count")
.do(-> store.incrementClicksCount())
Rx.Observable.merge(
incrementClickStream
# some more actions here for updating view ...
).subscribe(
-> view.setProps getViewState(store)
(err) ->
console.error? err)
RxReact (simple click count)
stream from view for increment and storage
modification
dispatchActions = (view, eventStream, store) ->
incrementClickStream = eventStream
.filter(({action}) -> action is "increment_click_count")
.do(-> store.incrementClicksCount())
Rx.Observable.merge(
incrementClickStream
# some more actions here for updating view ...
).subscribe(
-> view.setProps getViewState(store)
(err) ->
console.error? err)
RxReact (simple click count)
merge all streams that can modify UI
dispatchActions = (view, eventStream, store) ->
incrementClickStream = eventStream
.filter(({action}) -> action is "increment_click_count")
.do(-> store.incrementClicksCount())
Rx.Observable.merge(
incrementClickStream
# some more actions here for updating view ...
).subscribe(
-> view.setProps getViewState(store)
(err) ->
console.error? err)
RxReact (simple click count)
update UI, making setProps on view
component
RxReact (simple click count)
More complex case
1. Decrement.
2. Sync with server (per 1 second).
3. Sync only if value changed.
4. Show sync success message.
5. Hide success message after 2 seconds.
demo - http://alexmost.github.io/RxReact/hello_world2/public/index.html
code - https://github.com/AlexMost/RxReact/tree/master/hello_world2/hello_world2
dispatchActions = (view, eventStream, store) ->
incrementClickStream = ...
decrementClickStream = eventStream
.filter(({action}) -> action is "decrement_click_count")
.do(-> store.decrementClickscount())
.share()
countClicksStream = Rx.Observable
.merge(incrementClickStream, decrementClickStream)
showSavedMessageStream = countClicksStream
.throttle(1000)
.distinct(-> store.getClicksCount())
.flatMap(-> saveToDb store.getClicksCount())
.do(-> store.enableSavedMessage())
hideSavedMessageStream = showSavedMessageStream.delay(2000)
.do(-> store.disableSavedMessage())
// merge ...
dispatchActions = (view, eventStream, store) ->
incrementClickStream = ...
decrementClickStream = eventStream
.filter(({action}) -> action is "decrement_click_count")
.do(-> store.decrementClickscount())
.share()
countClicksStream = Rx.Observable
.merge(incrementClickStream, decrementClickStream)
showSavedMessageStream = countClicksStream
.throttle(1000)
.distinct(-> store.getClicksCount())
.flatMap(-> saveToDb store.getClicksCount())
.do(-> store.enableSavedMessage())
hideSavedMessageStream = showSavedMessageStream.delay(2000)
.do(-> store.disableSavedMessage())
// merge ...
decrement click stream
dispatchActions = (view, eventStream, store) ->
incrementClickStream = ...
decrementClickStream = eventStream
.filter(({action}) -> action is "decrement_click_count")
.do(-> store.decrementClickscount())
.share()
countClicksStream = Rx.Observable
.merge(incrementClickStream, decrementClickStream)
showSavedMessageStream = countClicksStream
.throttle(1000)
.distinct(-> store.getClicksCount())
.flatMap(-> saveToDb store.getClicksCount())
.do(-> store.enableSavedMessage())
hideSavedMessageStream = showSavedMessageStream.delay(2000)
.do(-> store.disableSavedMessage())
// merge ...
using merge to produce all clicks stream
dispatchActions = (view, eventStream, store) ->
incrementClickStream = ...
decrementClickStream = eventStream
.filter(({action}) -> action is "decrement_click_count")
.do(-> store.decrementClickscount())
.share()
countClicksStream = Rx.Observable
.merge(incrementClickStream, decrementClickStream)
showSavedMessageStream = countClicksStream
.throttle(1000)
.distinct(-> store.getClicksCount())
.flatMap(-> saveToDb store.getClicksCount())
.do(-> store.enableSavedMessage())
hideSavedMessageStream = showSavedMessageStream.delay(2000)
.do(-> store.disableSavedMessage())
// merge ...
per 1 second
if clicks counter value changed
sync with server, wait for responce
showsuccesss message
dispatchActions = (view, eventStream, store) ->
incrementClickStream = ...
decrementClickStream = eventStream
.filter(({action}) -> action is "decrement_click_count")
.do(-> store.decrementClickscount())
.share()
countClicksStream = Rx.Observable
.merge(incrementClickStream, decrementClickStream)
showSavedMessageStream = countClicksStream
.throttle(1000)
.distinct(-> store.getClicksCount())
.flatMap(-> saveToDb store.getClicksCount())
.do(-> store.enableSavedMessage())
hideSavedMessageStream = showSavedMessageStream.delay(2000)
.do(-> store.disableSavedMessage())
// merge ...
create hide message stream
from previous
Conclusion
● Rx is a powerful tool for writing async code
● Helps to write modular and composable code
● Solves a lot of hard testing problems
● Solves problem of error handling and resource
management
Resources
http://rxmarbles.com/
http://jaredforsyth.com/rxvision/
https://github.com/jhusain/learnrx
Talk demos here
https://github.com/AlexMost/kyivjs_2015
Thanks : D

Mais conteúdo relacionado

Mais procurados

如何「畫圖」寫測試 - RxJS Marble Test
如何「畫圖」寫測試 - RxJS Marble Test如何「畫圖」寫測試 - RxJS Marble Test
如何「畫圖」寫測試 - RxJS Marble Test名辰 洪
 
Compose Async with RxJS
Compose Async with RxJSCompose Async with RxJS
Compose Async with RxJSKyung Yeol Kim
 
서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015
서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015
서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015NAVER / MusicPlatform
 
RxJS - 封裝程式的藝術
RxJS - 封裝程式的藝術RxJS - 封裝程式的藝術
RxJS - 封裝程式的藝術名辰 洪
 
Expert JavaScript tricks of the masters
Expert JavaScript  tricks of the mastersExpert JavaScript  tricks of the masters
Expert JavaScript tricks of the mastersAra Pehlivanian
 
Shift Remote FRONTEND: Reactivity in Vue.JS 3 - Marko Boskovic (Barrage)
Shift Remote FRONTEND: Reactivity in Vue.JS 3 - Marko Boskovic (Barrage)Shift Remote FRONTEND: Reactivity in Vue.JS 3 - Marko Boskovic (Barrage)
Shift Remote FRONTEND: Reactivity in Vue.JS 3 - Marko Boskovic (Barrage)Shift Conference
 
RxJS Operators - Real World Use Cases (FULL VERSION)
RxJS Operators - Real World Use Cases (FULL VERSION)RxJS Operators - Real World Use Cases (FULL VERSION)
RxJS Operators - Real World Use Cases (FULL VERSION)Tracy Lee
 
RxJS101 - What you need to know to get started with RxJS tomorrow
RxJS101 - What you need to know to get started with RxJS tomorrowRxJS101 - What you need to know to get started with RxJS tomorrow
RxJS101 - What you need to know to get started with RxJS tomorrowViliam Elischer
 
Angular and The Case for RxJS
Angular and The Case for RxJSAngular and The Case for RxJS
Angular and The Case for RxJSSandi Barr
 
Concurrent applications with free monads and stm
Concurrent applications with free monads and stmConcurrent applications with free monads and stm
Concurrent applications with free monads and stmAlexander Granin
 
Add Some Fun to Your Functional Programming With RXJS
Add Some Fun to Your Functional Programming With RXJSAdd Some Fun to Your Functional Programming With RXJS
Add Some Fun to Your Functional Programming With RXJSRyan Anklam
 
Solid principles in practice the clean architecture - Droidcon Italy
Solid principles in practice the clean architecture - Droidcon ItalySolid principles in practice the clean architecture - Droidcon Italy
Solid principles in practice the clean architecture - Droidcon ItalyFabio Collini
 
SOLID principles in practice: the Clean Architecture
SOLID principles in practice: the Clean ArchitectureSOLID principles in practice: the Clean Architecture
SOLID principles in practice: the Clean ArchitectureFabio Collini
 
Think Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSThink Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSAdam L Barrett
 
Virtual machine and javascript engine
Virtual machine and javascript engineVirtual machine and javascript engine
Virtual machine and javascript engineDuoyi Wu
 
Functional Reactive Programming with RxJS
Functional Reactive Programming with RxJSFunctional Reactive Programming with RxJS
Functional Reactive Programming with RxJSstefanmayer13
 

Mais procurados (20)

如何「畫圖」寫測試 - RxJS Marble Test
如何「畫圖」寫測試 - RxJS Marble Test如何「畫圖」寫測試 - RxJS Marble Test
如何「畫圖」寫測試 - RxJS Marble Test
 
Compose Async with RxJS
Compose Async with RxJSCompose Async with RxJS
Compose Async with RxJS
 
서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015
서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015
서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015
 
RxJS - 封裝程式的藝術
RxJS - 封裝程式的藝術RxJS - 封裝程式的藝術
RxJS - 封裝程式的藝術
 
Oop assignment 02
Oop assignment 02Oop assignment 02
Oop assignment 02
 
Expert JavaScript tricks of the masters
Expert JavaScript  tricks of the mastersExpert JavaScript  tricks of the masters
Expert JavaScript tricks of the masters
 
Shift Remote FRONTEND: Reactivity in Vue.JS 3 - Marko Boskovic (Barrage)
Shift Remote FRONTEND: Reactivity in Vue.JS 3 - Marko Boskovic (Barrage)Shift Remote FRONTEND: Reactivity in Vue.JS 3 - Marko Boskovic (Barrage)
Shift Remote FRONTEND: Reactivity in Vue.JS 3 - Marko Boskovic (Barrage)
 
RxJS Operators - Real World Use Cases (FULL VERSION)
RxJS Operators - Real World Use Cases (FULL VERSION)RxJS Operators - Real World Use Cases (FULL VERSION)
RxJS Operators - Real World Use Cases (FULL VERSION)
 
RxJS101 - What you need to know to get started with RxJS tomorrow
RxJS101 - What you need to know to get started with RxJS tomorrowRxJS101 - What you need to know to get started with RxJS tomorrow
RxJS101 - What you need to know to get started with RxJS tomorrow
 
Angular and The Case for RxJS
Angular and The Case for RxJSAngular and The Case for RxJS
Angular and The Case for RxJS
 
Concurrent applications with free monads and stm
Concurrent applications with free monads and stmConcurrent applications with free monads and stm
Concurrent applications with free monads and stm
 
Add Some Fun to Your Functional Programming With RXJS
Add Some Fun to Your Functional Programming With RXJSAdd Some Fun to Your Functional Programming With RXJS
Add Some Fun to Your Functional Programming With RXJS
 
Solid principles in practice the clean architecture - Droidcon Italy
Solid principles in practice the clean architecture - Droidcon ItalySolid principles in practice the clean architecture - Droidcon Italy
Solid principles in practice the clean architecture - Droidcon Italy
 
SOLID principles in practice: the Clean Architecture
SOLID principles in practice: the Clean ArchitectureSOLID principles in practice: the Clean Architecture
SOLID principles in practice: the Clean Architecture
 
2 презентация rx java+android
2 презентация rx java+android2 презентация rx java+android
2 презентация rx java+android
 
Think Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSThink Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJS
 
Virtual machine and javascript engine
Virtual machine and javascript engineVirtual machine and javascript engine
Virtual machine and javascript engine
 
D3.js workshop
D3.js workshopD3.js workshop
D3.js workshop
 
Pellucid stm
Pellucid stmPellucid stm
Pellucid stm
 
Functional Reactive Programming with RxJS
Functional Reactive Programming with RxJSFunctional Reactive Programming with RxJS
Functional Reactive Programming with RxJS
 

Destaque

Destaque (6)

UX metrics
UX metricsUX metrics
UX metrics
 
Elm kyivfprog 2015
Elm kyivfprog 2015Elm kyivfprog 2015
Elm kyivfprog 2015
 
структура It компании
структура It компанииструктура It компании
структура It компании
 
Agile UX & OOUX
Agile UX & OOUXAgile UX & OOUX
Agile UX & OOUX
 
Modern javascript localization with c-3po and the good old gettext
Modern javascript localization with c-3po and the good old gettextModern javascript localization with c-3po and the good old gettext
Modern javascript localization with c-3po and the good old gettext
 
SlideShare 101
SlideShare 101SlideShare 101
SlideShare 101
 

Semelhante a Rxjs kyivjs 2015

WebCamp:Front-end Developers Day. Александр Мостовенко "Rx.js - делаем асинхр...
WebCamp:Front-end Developers Day. Александр Мостовенко "Rx.js - делаем асинхр...WebCamp:Front-end Developers Day. Александр Мостовенко "Rx.js - делаем асинхр...
WebCamp:Front-end Developers Day. Александр Мостовенко "Rx.js - делаем асинхр...GeeksLab Odessa
 
Luis Atencio on RxJS
Luis Atencio on RxJSLuis Atencio on RxJS
Luis Atencio on RxJSLuis Atencio
 
响应式编程及框架
响应式编程及框架响应式编程及框架
响应式编程及框架jeffz
 
Understanding Asynchronous JavaScript
Understanding Asynchronous JavaScriptUnderstanding Asynchronous JavaScript
Understanding Asynchronous JavaScriptjnewmanux
 
From zero to hero with the reactive extensions for JavaScript
From zero to hero with the reactive extensions for JavaScriptFrom zero to hero with the reactive extensions for JavaScript
From zero to hero with the reactive extensions for JavaScriptMaurice De Beijer [MVP]
 
Reactive Programming for a demanding world: building event-driven and respons...
Reactive Programming for a demanding world: building event-driven and respons...Reactive Programming for a demanding world: building event-driven and respons...
Reactive Programming for a demanding world: building event-driven and respons...Mario Fusco
 
Reactive Programming in Java by Mario Fusco - Codemotion Rome 2015
Reactive Programming in Java by Mario Fusco - Codemotion Rome 2015Reactive Programming in Java by Mario Fusco - Codemotion Rome 2015
Reactive Programming in Java by Mario Fusco - Codemotion Rome 2015Codemotion
 
Funtional Reactive Programming with Examples in Scala + GWT
Funtional Reactive Programming with Examples in Scala + GWTFuntional Reactive Programming with Examples in Scala + GWT
Funtional Reactive Programming with Examples in Scala + GWTVasil Remeniuk
 
Asynchronous web apps with the Play Framework 2.0
Asynchronous web apps with the Play Framework 2.0Asynchronous web apps with the Play Framework 2.0
Asynchronous web apps with the Play Framework 2.0Oscar Renalias
 
Introduction to RxJS
Introduction to RxJSIntroduction to RxJS
Introduction to RxJSBrainhub
 
From zero to hero with the reactive extensions for java script
From zero to hero with the reactive extensions for java scriptFrom zero to hero with the reactive extensions for java script
From zero to hero with the reactive extensions for java scriptMaurice De Beijer [MVP]
 
RxJava for Android - GDG DevFest Ukraine 2015
RxJava for Android - GDG DevFest Ukraine 2015RxJava for Android - GDG DevFest Ukraine 2015
RxJava for Android - GDG DevFest Ukraine 2015Constantine Mars
 
Reactive programming on Android
Reactive programming on AndroidReactive programming on Android
Reactive programming on AndroidTomáš Kypta
 
Asynchronous programming done right - Node.js
Asynchronous programming done right - Node.jsAsynchronous programming done right - Node.js
Asynchronous programming done right - Node.jsPiotr Pelczar
 

Semelhante a Rxjs kyivjs 2015 (20)

WebCamp:Front-end Developers Day. Александр Мостовенко "Rx.js - делаем асинхр...
WebCamp:Front-end Developers Day. Александр Мостовенко "Rx.js - делаем асинхр...WebCamp:Front-end Developers Day. Александр Мостовенко "Rx.js - делаем асинхр...
WebCamp:Front-end Developers Day. Александр Мостовенко "Rx.js - делаем асинхр...
 
Rxjs ngvikings
Rxjs ngvikingsRxjs ngvikings
Rxjs ngvikings
 
Rxjs marble-testing
Rxjs marble-testingRxjs marble-testing
Rxjs marble-testing
 
Rxjs swetugg
Rxjs swetuggRxjs swetugg
Rxjs swetugg
 
Luis Atencio on RxJS
Luis Atencio on RxJSLuis Atencio on RxJS
Luis Atencio on RxJS
 
响应式编程及框架
响应式编程及框架响应式编程及框架
响应式编程及框架
 
The Reactive Landscape
The Reactive LandscapeThe Reactive Landscape
The Reactive Landscape
 
Understanding Asynchronous JavaScript
Understanding Asynchronous JavaScriptUnderstanding Asynchronous JavaScript
Understanding Asynchronous JavaScript
 
Reactive x
Reactive xReactive x
Reactive x
 
From zero to hero with the reactive extensions for JavaScript
From zero to hero with the reactive extensions for JavaScriptFrom zero to hero with the reactive extensions for JavaScript
From zero to hero with the reactive extensions for JavaScript
 
Reactive Programming for a demanding world: building event-driven and respons...
Reactive Programming for a demanding world: building event-driven and respons...Reactive Programming for a demanding world: building event-driven and respons...
Reactive Programming for a demanding world: building event-driven and respons...
 
Reactive Programming in Java by Mario Fusco - Codemotion Rome 2015
Reactive Programming in Java by Mario Fusco - Codemotion Rome 2015Reactive Programming in Java by Mario Fusco - Codemotion Rome 2015
Reactive Programming in Java by Mario Fusco - Codemotion Rome 2015
 
Funtional Reactive Programming with Examples in Scala + GWT
Funtional Reactive Programming with Examples in Scala + GWTFuntional Reactive Programming with Examples in Scala + GWT
Funtional Reactive Programming with Examples in Scala + GWT
 
Asynchronous web apps with the Play Framework 2.0
Asynchronous web apps with the Play Framework 2.0Asynchronous web apps with the Play Framework 2.0
Asynchronous web apps with the Play Framework 2.0
 
Introduction to RxJS
Introduction to RxJSIntroduction to RxJS
Introduction to RxJS
 
From zero to hero with the reactive extensions for java script
From zero to hero with the reactive extensions for java scriptFrom zero to hero with the reactive extensions for java script
From zero to hero with the reactive extensions for java script
 
RxJava for Android - GDG DevFest Ukraine 2015
RxJava for Android - GDG DevFest Ukraine 2015RxJava for Android - GDG DevFest Ukraine 2015
RxJava for Android - GDG DevFest Ukraine 2015
 
Rx workshop
Rx workshopRx workshop
Rx workshop
 
Reactive programming on Android
Reactive programming on AndroidReactive programming on Android
Reactive programming on Android
 
Asynchronous programming done right - Node.js
Asynchronous programming done right - Node.jsAsynchronous programming done right - Node.js
Asynchronous programming done right - Node.js
 

Último

VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnAmarnathKambale
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrainmasabamasaba
 
SHRMPro HRMS Software Solutions Presentation
SHRMPro HRMS Software Solutions PresentationSHRMPro HRMS Software Solutions Presentation
SHRMPro HRMS Software Solutions PresentationShrmpro
 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park masabamasaba
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastPapp Krisztián
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareJim McKeeth
 
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdfPayment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdfkalichargn70th171
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension AidPhilip Schwarz
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplatePresentation.STUDIO
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisamasabamasaba
 
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdfThe Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdfayushiqss
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionOnePlan Solutions
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...masabamasaba
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdfPearlKirahMaeRagusta1
 
%in Durban+277-882-255-28 abortion pills for sale in Durban
%in Durban+277-882-255-28 abortion pills for sale in Durban%in Durban+277-882-255-28 abortion pills for sale in Durban
%in Durban+277-882-255-28 abortion pills for sale in Durbanmasabamasaba
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...Shane Coughlan
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Steffen Staab
 
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...masabamasaba
 

Último (20)

VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
SHRMPro HRMS Software Solutions Presentation
SHRMPro HRMS Software Solutions PresentationSHRMPro HRMS Software Solutions Presentation
SHRMPro HRMS Software Solutions Presentation
 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK Software
 
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdfPayment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdfThe Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdf
 
%in Durban+277-882-255-28 abortion pills for sale in Durban
%in Durban+277-882-255-28 abortion pills for sale in Durban%in Durban+277-882-255-28 abortion pills for sale in Durban
%in Durban+277-882-255-28 abortion pills for sale in Durban
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
 

Rxjs kyivjs 2015

  • 2. About me Mostovenko Alexander Python developer at Writing mostly in python and coffeescript. Love FP stuff. Traveling, snowboarding, cycling. https://twitter.com/MostovenkoA https://github.com/AlexMost
  • 3. Why Rx.js and not another FRP lib? ● Implemented in a lot of languages (.NET, Java, Ruby, Python, Clojure, Scala, Haskell, Objective-C). ● Has a huge amount of docs and examples. ● Why not?
  • 5. Async code in javascript ● Some computation with delayed result. (data fetch, animations, DOM operations) ● Reacting to events (event handlers)
  • 6. Sync vs Async dataflow
  • 17. Asynchronous dataflow (autocomplete) time Actions keyup per 2 seconds ajax request ajax response
  • 18. Asynchronous dataflow (autocomplete) time Actions keyup per 2 seconds ajax request ajax response show suggest
  • 19. Asynchronous dataflow (autocomplete) time Actions keyup per 2 seconds ajax request ajax response show suggest
  • 20. Asynchronous dataflow (autocomplete) time Actions keyup per 2 seconds ajax request ajax response show suggest Ooooops
  • 21. Problems with async code 1. How to manage async flow in code? 2. How to handle errors? 3. How to compose?
  • 23. Callbacks ● Event notification - Yes ● Manage control flow - Nooooooooooo
  • 24. Callback hell async_func1(function(err, data){ async_func2(function(err, data){ async_func3(function(err, data){ async_func4(function(err, data){ }); }); }); });
  • 25. Callback hell yeah !!! async_func1(function(err, data){ if (!err) { async_func2(function(err, data){ if (!err) { async_func3(function(err, data){ if (!err) { async_func4(function(err, data){ }); } else { log(err); } }); } else { log(err); } }); } else { log(err); } });
  • 26. Callback hell yeah !!! async_func1(function(err, data){ if (!err) { async_func2(function(err, data){ if (!err) { async_func3(function(err, data){ if (!err) { async_func4(function(err, data){ }); } else { log(err); } }); } else { log(err); } }); } else { log(err); } }); UNREADABLE !!! UNMANAGABLE !!! UNTESTABLE !!! UNCOMPOSABLE !!! PIECE OF …. CODE
  • 27.
  • 28. Monad A monad is just a monoid in the category of endofunctors
  • 29. Callback vs Black hole some_async_func(function(err, result) { // ... looks like we are in trap another_wonderful_func(function(err, result){ // ... you are in trap }); });
  • 30. Callback vs Black Hole 1. No return value (undefined)
  • 31. Callback vs Black Hole 1. No return value (undefined) 2. One way ticket (callback hell)
  • 33. Promise var promise = new Promise((resolve, reject) => { // ... some async staff }); promise.then( (result) => {}, (error) => {} )
  • 34. Promise 1. Step forward from callbacks for control flow managing 2. Error handling
  • 35. Why we should look at Observable? 1. Promise represents only single value. 2. How to cancel? 3. Lazy execution. 4. We can work with Observable as easy as with promise.
  • 36. Promise is Observable only with a single value
  • 37. Observable The Observable object represents a push based collection.
  • 38. Observable var source = Rx.Observable.create((observer) => // some async operation observer.onNext(data) // or .. observer.onError(data) // or .. observer.onCompleted(data) ); source.subscribe( (data) => {} (err) => {} )
  • 39. Observlable vs promise example var source = Rx.Observable.create((observer) => { setTimeout(() => { console.log("observable timeout hit"); observer.onNext(25); }, 500); console.log('observable started')}); source.subscribe(x => console.log(`observable value ${x}`)); Observable > observable started > observable timeout hit > observable value 25
  • 40. Observlable vs promise example var promise = new Promise((resolve) => { setTimeout(() => { console.log("promise timeout hit"); resolve(25); }, 500); console.log("promise started");}); promise.then(x => console.log(`promise value ${x}`)); Promise > promise started > promise timeout hit > promise value 25
  • 41. Lazy execution var source = Rx.Observable.create((observer) => { setTimeout(() => { console.log("observable timeout hit"); observer.onNext(25); }, 500); console.log('observable started')}); // source.subscribe(x => console.log(`observable value ${x}`)); >
  • 42. Observable can be canceled var source = Rx.Observable.create((observer) => { var id = setTimeout(() => { console.log("observable timeout hit"); observer.onNext(25); }, 500); console.log('observable started'); return () => { console.log("dispose called") clearTimeout(id);} }); var disposable = source.subscribe( x => console.log(`observable value ${x}`)); setTimeout(() => disposable.dispose(), 100) > observable started > dispose called
  • 43. Asynchronous programming landscape multiple values single value sync async a = f(x) a = f(x).then(...) collection = [1, 2, 3] a = collection .filter((v) => v > 2) Promise Array Sync value ?
  • 44. Asynchronous programming landscape multiple values single value sync async a = f(x) a = f(x).then(...) collection = [1, 2, 3] a = collection .filter((v) => v > 2) move = Rx.Observable.fromEvent(document, 'mousemove') my_moves = move .filter((ev) => ev.clientX > 100) my_moves.subscribe(...) Promise Array value Observable
  • 45. How to create Observable ● Observable.create ● Observable.fromEvent ● Observable.fromNodeCallback ● Observable.fromArray ● Observable.fromPromise
  • 46. Drag & Drop example What if i told you …. That mouse move event is an array and you can map, filter over it?
  • 47. var dragTarget = document.getElementById('dragTarget'); // Get the three major events collections var mouseup = Rx.DOM.fromEvent(dragTarget, 'mouseup'); var mousemove = Rx.DOM.fromEvent(document, 'mousemove'); var mousedown = Rx.DOM.fromEvent(dragTarget, 'mousedown'); var mousedrag = mousedown.flatMap(({offsetX, offsetY}) => { return mousemove .map(({clientX: x, clientY: y}) => { return {left: x - offsetX, top: y - offsetY}}) .takeUntil(mouseup) }); var subscription = mousedrag.subscribe((pos) => { dragTarget.style.top = pos.top + 'px'; dragTarget.style.left = pos.left + 'px'; });
  • 48. var dragTarget = document.getElementById('dragTarget'); // Get the three major events collections var mouseup = Rx.DOM.fromEvent(dragTarget, 'mouseup'); var mousemove = Rx.DOM.fromEvent(document, 'mousemove'); var mousedown = Rx.DOM.fromEvent(dragTarget, 'mousedown'); var mousedrag = mousedown.flatMap(({offsetX, offsetY}) => { return mousemove .map(({clientX: x, clientY: y}) => { return {left: x - offsetX, top: y - offsetY}}) .takeUntil(mouseup) }); var subscription = mousedrag.subscribe((pos) => { dragTarget.style.top = pos.top + 'px'; dragTarget.style.left = pos.left + 'px'; }); Create observable collections from DOM events
  • 49. var dragTarget = document.getElementById('dragTarget'); // Get the three major events collections var mouseup = Rx.DOM.fromEvent(dragTarget, 'mouseup'); var mousemove = Rx.DOM.fromEvent(document, 'mousemove'); var mousedown = Rx.DOM.fromEvent(dragTarget, 'mousedown'); var mousedrag = mousedown.flatMap(({offsetX, offsetY}) => { return mousemove .map(({clientX: x, clientY: y}) => { return {left: x - offsetX, top: y - offsetY}}) .takeUntil(mouseup) }); var subscription = mousedrag.subscribe((pos) => { dragTarget.style.top = pos.top + 'px'; dragTarget.style.left = pos.left + 'px'; }); Using power of Rx, combine existing event streams to produce mouse drag event collection
  • 50. var dragTarget = document.getElementById('dragTarget'); // Get the three major events collections var mouseup = Rx.DOM.fromEvent(dragTarget, 'mouseup'); var mousemove = Rx.DOM.fromEvent(document, 'mousemove'); var mousedown = Rx.DOM.fromEvent(dragTarget, 'mousedown'); var mousedrag = mousedown.flatMap(({offsetX, offsetY}) => { return mousemove .map(({clientX: x, clientY: y}) => { return {left: x - offsetX, top: y - offsetY}}) .takeUntil(mouseup) }); var subscription = mousedrag.subscribe((pos) => { dragTarget.style.top = pos.top + 'px'; dragTarget.style.left = pos.left + 'px'; }); Subscribe on mouse drag events, updating top and left attributes
  • 51. Observable are first class events Can be: - passed as a parameter - returned from a function - assigned to a variable
  • 52.
  • 53. Some common basic operations map filter reduce zip merge flatMap ... https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/observable.md
  • 56. var mousedrag_in_area = mousedrag.filter(({top, left}) => { return top <= 200 && left <= 200 }); var subscription = mousedrag_in_area.subscribe((pos) => { dragTarget.style.top = pos.top + 'px'; dragTarget.style.left = pos.left + 'px'; }); let’s filter drag area
  • 58. let’s create slow mouse drag var slow_mousedrag = mousedrag.delay(700) var subscription = slow_mousedrag.subscribe((pos) => { dragTarget.style.top = pos.top + 'px'; dragTarget.style.left = pos.left + 'px'; });
  • 60. let’s record our drag path var drag_path = mousedrag .takeUntil(mouseup) .reduce(((a, b) => a + `${b.top} ${b.left};`), "") drag_path.subscribe((path) => pathTarget.innerHTML = path)
  • 62. flatMap var mousedrag = mousedown.flatMap(({offsetX, offsetY}) => { return mousemove .map(({clientX: x, clientY: y}) => { return {left: x - offsetX, top: y - offsetY}}) .takeUntil(mouseup) });
  • 63. flatMap var mousedrag = mousedown.flatMap(({offsetX, offsetY}) => { return mousemove .map(({clientX: x, clientY: y}) => { return {left: x - offsetX, top: y - offsetY}}) .takeUntil(mouseup) }); Outer stream
  • 64. flatMap var mousedrag = mousedown.flatMap(({offsetX, offsetY}) => { return mousemove .map(({clientX: x, clientY: y}) => { return {left: x - offsetX, top: y - offsetY}}) .takeUntil(mouseup) }); value as a stream
  • 66. merge var btnTarget = document.getElementById('okbtn'); var buttonClicks = Rx.DOM.fromEvent(btnTarget, 'click'); var move_to_100 = buttonClicks.map(() => {return {left: 100, top: 100}}); var change_position = Rx.Observable.merge(mousedrag, move_to_100) change_position.subscribe((pos) => { dragTarget.style.top = pos.top + 'px'; dragTarget.style.left = pos.left + 'px'; });
  • 67. merge var btnTarget = document.getElementById('okbtn'); var buttonClicks = Rx.DOM.fromEvent(btnTarget, 'click'); var move_to_100 = buttonClicks.map(() => {return {left: 100, top: 100}}); var change_position = Rx.Observable.merge(mousedrag, move_to_100) change_position.subscribe((pos) => { dragTarget.style.top = pos.top + 'px'; dragTarget.style.left = pos.left + 'px'; }); new stream
  • 68. And a lot of other methods …. ● amb ● and ● asObservable ● average ● buffer ● bufferWithCount ● bufferWithTime ● bufferWithTimeOrCount ● catch | catchError ● combineLatest ● concat ● concatAll ● concatMap ● concatMapObserver ● connect ● includes ● controlled ● count ● debounce ● debounceWithSelector ● defaultIfEmpty ● delay ● delaySubscription ● delayWithSelector ● dematerialize ● distinct ● distinctUntilChanged ● do ● doOnNext ● doOnError ● doOnCompleted ● doWhile ● elementAt ● elementAtOrDefault ● every ● expand ● extend ● filter ● find ● findIndex ● first ● firstOrDefault ● flatMap ● flatMapObserver ● flatMapLatest ● forkJoin ● groupBy ● groupByUntil ● groupJoin ● ignoreElements ● indexOf ● isEmpty ● join ● jortSort ● jortSortUntil ● last ● lastOrDefault ● merge ● mergeAll ● min ● minBy ● multicast ● observeOn ● onErrorResumeNext ● pairwise ● partition ● pausable ● pausableBuffered ● pluck ● publish ● publishLast ● publishValue ● share ● shareReplay ● shareValue ● refCount ● reduce ● repeat ● replay ● retry ● retryWhen ● sample ● scan ● select ● selectConcat ● selectConcatObserver ● selectMany ● selectManyObserver ● selectSwitch ● sequenceEqual ● single ● singleOrDefault ● singleInstance ● skip ● skipLast ● skipLastWithTime ● skipUntil https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/observable.md
  • 69. Testing with time machine Rx.TestScheduler
  • 70. var mult_stream = some_stream.debounce(100).map((n) => n * 2) assertRxActions( mult_stream, [ [100, {value: 20}], [200, {value: 40}] ], [ [200, {value: 80}] ], (result) => assertTrue(result) )
  • 71. var mult_stream = some_stream.debounce(100).map((n) => n * 2) assertRxActions( mult_stream, [ [100, {value: 20}], [200, {value: 40}] ], [ [200, {value: 80}] ], (result) => assertTrue(result) ) stream to test
  • 72. var mult_stream = some_stream.debounce(100).map((n) => n * 2) assertRxActions( mult_stream, [ [100, {value: 20}], [200, {value: 40}] ], [ [200, {value: 80}] ], (result) => assertTrue(result) ) Input stream messages
  • 73. var mult_stream = some_stream.debounce(100).map((n) => n * 2) assertRxActions( mult_stream, [ [100, {value: 20}], [200, {value: 40}] ], [ [200, {value: 80}] ], (result) => assertTrue(result) ) time
  • 74. var mult_stream = some_stream.debounce(100).map((n) => n * 2) assertRxActions( mult_stream, [ [100, {value: 20}], [200, {value: 40}] ], [ [200, {value: 80}] ], (result) => assertTrue(result) ) Expected result at time
  • 75. var mult_stream = some_stream.debounce(100).map((n) => n * 2) assertRxActions( mult_stream, [ [100, {value: 20}], [200, {value: 40}] ], [ [200, {value: 80}] ], (result) => assertTrue(result) ) callback for assert
  • 76. React ? ● Rx-React ● RxReact ● cycle-react ● React RxJS Autocomplete ● React RxJS TODO MVC ● Rx TODO MVC ● React RxJS Router ● React + RxJS + Angular 2.0 di.js TODO MVC ● React + RxJS Reactive Cube ● Real-Time with React + RxJS + Meteor ● React + RxJS Flow ● Reactive Widgets ● React RxJS Infinite Scroll
  • 77. Flux ? ● Rx-Flux ● ReactiveFlux ● Thundercats.js ● Flurx ● RR
  • 78. RxReact some info - http://habrahabr.ru/post/251835/ repo with demos - https://github.com/AlexMost/RxReact
  • 79. RxReact (simple click count) Simple case demo - http://alexmost.github.io/RxReact/hello_world/public/index.html code - https://github.com/AlexMost/RxReact/tree/master/hello_world/hello_world
  • 80. dispatchActions = (view, eventStream, store) -> incrementClickStream = eventStream .filter(({action}) -> action is "increment_click_count") .do(-> store.incrementClicksCount()) Rx.Observable.merge( incrementClickStream # some more actions here for updating view ... ).subscribe( -> view.setProps getViewState(store) (err) -> console.error? err) RxReact (simple click count)
  • 81. dispatchActions = (view, eventStream, store) -> incrementClickStream = eventStream .filter(({action}) -> action is "increment_click_count") .do(-> store.incrementClicksCount()) Rx.Observable.merge( incrementClickStream # some more actions here for updating view ... ).subscribe( -> view.setProps getViewState(store) (err) -> console.error? err) RxReact (simple click count) stream from view for increment and storage modification
  • 82. dispatchActions = (view, eventStream, store) -> incrementClickStream = eventStream .filter(({action}) -> action is "increment_click_count") .do(-> store.incrementClicksCount()) Rx.Observable.merge( incrementClickStream # some more actions here for updating view ... ).subscribe( -> view.setProps getViewState(store) (err) -> console.error? err) RxReact (simple click count) merge all streams that can modify UI
  • 83. dispatchActions = (view, eventStream, store) -> incrementClickStream = eventStream .filter(({action}) -> action is "increment_click_count") .do(-> store.incrementClicksCount()) Rx.Observable.merge( incrementClickStream # some more actions here for updating view ... ).subscribe( -> view.setProps getViewState(store) (err) -> console.error? err) RxReact (simple click count) update UI, making setProps on view component
  • 84. RxReact (simple click count) More complex case 1. Decrement. 2. Sync with server (per 1 second). 3. Sync only if value changed. 4. Show sync success message. 5. Hide success message after 2 seconds. demo - http://alexmost.github.io/RxReact/hello_world2/public/index.html code - https://github.com/AlexMost/RxReact/tree/master/hello_world2/hello_world2
  • 85. dispatchActions = (view, eventStream, store) -> incrementClickStream = ... decrementClickStream = eventStream .filter(({action}) -> action is "decrement_click_count") .do(-> store.decrementClickscount()) .share() countClicksStream = Rx.Observable .merge(incrementClickStream, decrementClickStream) showSavedMessageStream = countClicksStream .throttle(1000) .distinct(-> store.getClicksCount()) .flatMap(-> saveToDb store.getClicksCount()) .do(-> store.enableSavedMessage()) hideSavedMessageStream = showSavedMessageStream.delay(2000) .do(-> store.disableSavedMessage()) // merge ...
  • 86. dispatchActions = (view, eventStream, store) -> incrementClickStream = ... decrementClickStream = eventStream .filter(({action}) -> action is "decrement_click_count") .do(-> store.decrementClickscount()) .share() countClicksStream = Rx.Observable .merge(incrementClickStream, decrementClickStream) showSavedMessageStream = countClicksStream .throttle(1000) .distinct(-> store.getClicksCount()) .flatMap(-> saveToDb store.getClicksCount()) .do(-> store.enableSavedMessage()) hideSavedMessageStream = showSavedMessageStream.delay(2000) .do(-> store.disableSavedMessage()) // merge ... decrement click stream
  • 87. dispatchActions = (view, eventStream, store) -> incrementClickStream = ... decrementClickStream = eventStream .filter(({action}) -> action is "decrement_click_count") .do(-> store.decrementClickscount()) .share() countClicksStream = Rx.Observable .merge(incrementClickStream, decrementClickStream) showSavedMessageStream = countClicksStream .throttle(1000) .distinct(-> store.getClicksCount()) .flatMap(-> saveToDb store.getClicksCount()) .do(-> store.enableSavedMessage()) hideSavedMessageStream = showSavedMessageStream.delay(2000) .do(-> store.disableSavedMessage()) // merge ... using merge to produce all clicks stream
  • 88. dispatchActions = (view, eventStream, store) -> incrementClickStream = ... decrementClickStream = eventStream .filter(({action}) -> action is "decrement_click_count") .do(-> store.decrementClickscount()) .share() countClicksStream = Rx.Observable .merge(incrementClickStream, decrementClickStream) showSavedMessageStream = countClicksStream .throttle(1000) .distinct(-> store.getClicksCount()) .flatMap(-> saveToDb store.getClicksCount()) .do(-> store.enableSavedMessage()) hideSavedMessageStream = showSavedMessageStream.delay(2000) .do(-> store.disableSavedMessage()) // merge ... per 1 second if clicks counter value changed sync with server, wait for responce showsuccesss message
  • 89. dispatchActions = (view, eventStream, store) -> incrementClickStream = ... decrementClickStream = eventStream .filter(({action}) -> action is "decrement_click_count") .do(-> store.decrementClickscount()) .share() countClicksStream = Rx.Observable .merge(incrementClickStream, decrementClickStream) showSavedMessageStream = countClicksStream .throttle(1000) .distinct(-> store.getClicksCount()) .flatMap(-> saveToDb store.getClicksCount()) .do(-> store.enableSavedMessage()) hideSavedMessageStream = showSavedMessageStream.delay(2000) .do(-> store.disableSavedMessage()) // merge ... create hide message stream from previous
  • 90. Conclusion ● Rx is a powerful tool for writing async code ● Helps to write modular and composable code ● Solves a lot of hard testing problems ● Solves problem of error handling and resource management