SlideShare une entreprise Scribd logo
1  sur  93
Télécharger pour lire hors ligne
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

Contenu connexe

Tendances

如何「畫圖」寫測試 - 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
 

Tendances (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
 

En vedette

En vedette (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
 

Similaire à 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 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
 
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
 
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
 

Similaire à 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 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
 
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...
 
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
 

Dernier

Test Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendTest Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendArshad QA
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)OPEN KNOWLEDGE GmbH
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsAndolasoft Inc
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️anilsa9823
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackVICTOR MAESTRE RAMIREZ
 
Active Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfActive Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfCionsystems
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
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
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideChristina Lin
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...OnePlan Solutions
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...MyIntelliSource, Inc.
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfkalichargn70th171
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AIABDERRAOUF MEHENNI
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 

Dernier (20)

Test Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendTest Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and Backend
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStack
 
Active Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfActive Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdf
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
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
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 

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