SlideShare una empresa de Scribd logo
1 de 78
RxJs - demystified
Christoffer Noring
@chris_noring
Lodash for async
Who am I
@chris_noring
What is reactive programming?
Is a programming paradigm
Focuses on propagating changes
without us having to explicitly specify how the propagation happens
State what our code should to
without having to code every line
Functional programming
Avoid mutable state
Avoid side-effects
Functional composition over object composition
= programs with predictable outcome
Functional over imperative
var list = [ 1,2,3,4,5 ];
var newList = list.map( function(value) {
return value + 1;
})
Produces a new list
list NOT mutated/changed
but projected
Functional
Imperative
var list = [ 1,2,3,4,5 ];
list.forEach( function(value) {
value += 1;
})
X number invocation changes state
Reactive programming
Async data streams
Turn
click events
user inputs
data from server
callbacks into a stream
One paradigm/ api to rule them all
Observable pattern
Iterative pattern
Observer
Observable, observable sequence
= Rx pattern
Emits its values in order, like an iterator,
BUT pushes values as they become available
Has access to a producer in an observable pattern
Push-based behaviour,
don’t call us, we’ll call you
Consumer of an observable
Like listener in observable pattern
Doesn’t start streaming unless it has at least
one Observer subscribed to it
At the heart of everything is the
Observable
Promise vs Array vs
Observable
list
.map( x = > x.prop )
.filter( x => x > 2 )
.take( 2 )
list
.map( x = > x.prop )
.filter( x => x > 2 )
.take( 2 )
.subscribe(
x => console.log(x),
)
Array Observable
Promise
service.get()
.then( x => console.log(x) )
)
Array like,
handles async
but can also
- Cancelled
- Retried
Observable vs Observable pattern
function Producer(){
this.listeners = [];
}
Producer.prototype.add = function(listener){
this.listeners.push( listener );
}
Producer.prototype.notify = function(message){
this.listeners.forEach( function(listener){
listener.update( message );
})
}
var stream = new Rx.Observable(function(observer) {
observer.onNext('message');
})
stream.subscribe( function(val){
console.log( val );
})
Observable is usually NOT the producer,
it has access to one though
var stream = new Rx.Observable(function(observer){
var producer = new Producer();
producer.nextValue( function(val){
observer.onNext( val );
})
})
function Producer(){
}
Producer.prototype.nextValue = function(cb){
setTimeout(function(){
cb( 1 );
},2000);
}
Producer created internally =
“cold observable”
Also responsible for emitting value
to observer
Observable
Rx.Observable.create(
onValueCallback,
onErrorCallback,
onCompletedCallback
)
Optional
Marble diagrams
Operation
Stream
Other stream
Resulting stream
1 2 3
4 5
1 2 3 4 5
Most operators are covered at rxmarbles.com
Observable
with error
var stream = Rx.Observable.create(function(observer){
observer.onNext(1);
observer.onNext(2);
observer.onNext(3);
observer.onError( ‘there is an error’ )
})
stream.subscribe(
function(data){ console.log( data ); },
function(error) { console.error( error ); }
)
Observable
with completed
var stream = Rx.Observable.create(function(observer){
observer.onNext( 1 );
observer.onNext( 2 );
observer.onNext( 3 );
observer.onCompleted();
})
stream.subscribe(
function(data){ console.log( data ); },
function(error){ console.error( error ); },
function(){ console.info( “completed” ); }
)
Observable
cancelling
var homemadeStream = Rx.Observable.create((observer) => {
var i=0;
var handle = setInterval(function() {
observer.onNext( i++ );
}, 500);
return function(){
console.log('Disposing timeout');
clearTimeout( handle );
}
});
var subscription2 = homemadeStream.subscribe((val) => {
console.log('Homemade val',val);
});
setTimeout(function() {
console.log('Cancelling homemadeStream');
subscription2.dispose();
}, 1500);
Define whats to happen on dispose
Calling dispose
Produce values till someone calls dispose
Observable
create your own
var stream = Rx.Observable.create(function(observer){
observer.onNext(1);
observer.onNext(2);
observer.onNext(3);
})
stream.subscribe( function(data){ console.log( data ); } )
Stream 1 2 3
onNext() onNext()
Observable
wrap ajax
var stream = Rx.Observable.create(function(observer){
var request = new XMLHttpRequest();
request.open( ‘GET’, ‘url’ );
request.onload = function(){
if(request.status === 200) {
observer.onNext( request.response );
observer.onCompleted();
} else {
observer.onError( new Error( request.statusText ) )
}
}
request.onerror = function(){ observer.onError( new Error(‘unknown error’) ); }
request.send();
})
stream.subscribe( function(result) { console.log( result ); } )
Producer
Operators
120+ operators
Combination Conditional
Creational
Error handling
Multicasting
Filtering
Transformation
Utility
Categories
Operators
multicasting
Cold observable = producer is not shared
var cold = new Observable((observer) => {
var producer = new Producer();
// have observer listen to producer here
});
var producer = new Producer();
var hot = new Observable((observer) => {
// have observer listen to producer here
});
A producer is the source of values for your observable.
Operators
multicasting
Going from hot to cold
Operators
multicasting
var stream = Rx.Observable.interval(1000);
stream.subscribe(function(val){
console.log('Subscriber 1', val);
});
stream.subscribe(function(val){
console.log('Subscriber 2', val);
});
By definition cold,
as both subscriber start from 0,1 ..
NOT shared
Subscriber 1 ,0
Subscriber 2 ,0
Starts on same number
Operators
multicasting
How to share?
stream.subscribe(function(val){
console.log('Subscriber 1', val);
});
setTimeout(function() {
stream.connect();
}, 2000);
setTimeout(function() {
stream.subscribe(function(val){
console.log('Started after 4 sec, Subscriber 2', val);
});
}, 4000);
var stream = Rx.Observable.interval(1000)
.publish();
Sits and wait til
Observable,
creating
Rx.Observable.fromArray([ 1,2,3,4 ])
Rx.Observable.fromEvent(element, ‘event’);
Rx.Observable.fromArray(eventEmitter, ‘data’, function(){})
Rx.Observable.fromNodeCallback(fs.createFile)
Rx.Observable.fromCallback(obj.callback)
Rx.Observable.fromPromise(promise)
Rx.Observable.fromIterable(function *() { yield 20 })
Rx.Observable.range(1,3)
Rx.Observable.interval(miliseconds)
Observable
common operators
var stream = Rx.Observable.of(1,2,3,4,5);
stream.map((val) => {
return val + 1;
})
.filter((val) => {
return val % 3 === 0;
})
Investigates every value
Observable
reducer
var stream2 = Rx.Observable.of(1,2,3,4,5,6);
var subscription2 = stream2.reduce((acc, curr) => {
return acc + curr;
});
subscription2.subscribe((val) => {
console.log('Sum', val);
})
Operators
utility
Operators
utility
var stream = Rx.Observable.of(1,2,3,4,5);
var subscription = stream
.do(function(val){
console.log('Current val', val);
})
.filter(function(val){
return val % 2 === 0;
});
subscription.subscribe(function(val){
console.log('Val',val);
})
Echos every value
without changing it,
used for logging
Do
Operators
utility
toPromise Used to create a promise
from an observable
stream
.filter(function(val){
return val % 2 === 0;
})
.toPromise()
.then( function(val){
console.log('Promise', val);
}) 4
var stream = Rx.Observable.of(1,2,3,4,5);
Only latest value that fulfils filter is returned
Operators
utility
let
stream
.let( observable =>
observable
.filter(function(x){
return x % 2 > 0;
}))
.take(2)
.subscribe(function(val){
console.log('let', val);
})
Let’s us operate on the
observable.
We don’t need to return
what we do
like with a normal operator
stream
.filter(function(val){
return val % 2 === 0;
})
var stream = Rx.Observable.of(1,2,3,4,5);
Operators
utilityDelay,
the whole sequence
stream
.delay(1000)
.subscribe( (val) => {
var newTime = new Date().getTime();
console.log('Delayed', val + " " + (newTime - time));
})
Rx.Observable.merge(
Rx.Observable.of('Marco').delay(1000),
Rx.Observable.of('Polo').delay(2000)
).subscribe((val) => {
var newTime = new Date().getTime();
console.log('Merged Delay', val + " " + (newTime - time));
})
….. 1 second
1
2
3
….. 1 second
Marco
….. 2 second
Polo
Operators
combination
Operators
combination
concat
merge
var concat = Rx.Observable.concat(
stream,
stream2
);
var stream = Rx.Observable.fromArray([1,2,3,4]);
var stream2 = Rx.Observable.fromArray([5,6,7,8]);
1, 2, 3, 4, 5, 6, 7 ,8
var merge = Rx.Observable.merge(
stream,
stream2
);
1, 5, 2, 6, 3, 7, 4 ,8
first stream emits all values
then remaining value
streams take turn
There is difference so choose wisely
Operators
combination
var stream = Rx.Observable.fromArray([1,2,3,4]);
var stream2 = Rx.Observable.fromArray([5,6,7,8]);
var combineLatest = Rx.Observable.combineLatest(
stream,
stream2
);
combineLatest.subscribe( function(val) {
console.log( 'combine ', val )
})
combineLatest
[1,5], [2,6], [3,7], [4,8]
Operators
conditional
Operators
conditional
var stream =
Rx.Observable
.fromArray([1,2,3,4])
.every( function(val){
return val % 2 === 0;
});
false
var evenStream =
Rx.Observable
.fromArray([2,4,8])
.every( function(val){
return val % 2 === 0
});
true
Condition needs to be fulfilled on all values
Operators
filtering
Operators
filtering
var debounceTime = Rx.Observable
.fromEvent(button,'click')
.debounce(2000);
debounceTime.subscribe( function(){
console.log('mouse pressed');
})
waits x ms and
returns latest emitted
var debouncedStream = Rx.Observable
.fromArray([1,2])
.debounce(25);
debouncedStream.subscribe( function(val){
console.log('debounce stream', val );
});
returns 2
ex1
ex2
Ignores all generated
mouse click events
for 2 seconds
Operators
filtering
var mousePressedTimer = Rx.Observable.interval(1000);
mousePressedTimer
.takeUntil( mouseUp )
.subscribe( function(val){
console.log('mouse up has NOT happened yet',val);
}, function(err){},
function(){
console.log('condition fulfilled');
})
var mouseUp = Rx.Observable.fromEvent(button,'mouseup');
Break condition
Generate numbers
var throttle = Rx.Observable
.interval( 1000 )
.throttle( 1000 );
throttle.subscribe( function(val){
console.log('Throttle', val );
});
Operators
filtering
Delay every value
by x milliseconds
Throttle
1 2 3 4
1 2
Operators
transformation
Operators
transformation
var numbers = Rx.Observable.interval(1000);
var bufferBy = Rx.Observable.fromEvent(document,'click');
var buffered = numbers.buffer( bufferBy );
buffered.subscribe(function(values){
console.log('Buffered',values);
});
[1,2]
[3,4,5,6,7]
etc…
Numbers are generated to a buffer
until condition is met,
then the buffer content is emitted
Buffer
Operators
transformation
var bufferTime = numbers.bufferTime(2000);
bufferTime.subscribe(function(values){
console.log("Buffer time",values);
})
var numbers = Rx.Observable.interval(1000);
Waits x miliseconds and then emits buffer
BufferTime
var expand = Rx.Observable
.of(2)
.expand(function(val){
return Rx.Observable.of(1 + val);
})
.take(3);
expand.subscribe(function(val){
console.log('Expand',val);
})
Operators
transformationExpand
Recursively call provided callback
x times
Operators
transformation
Scan
var scanning = Rx.Observable
.of({ prop : 'a'}, { prop2 : 'b'})
.scan((acc, curr) => Object.assign({}, acc, curr), {});
scanning.subscribe( function(val){
console.log( val );
});
Add accumulated
and current
var sum = Rx.Observable
.of(1,2,3)
.do(function(){
console.log('Create side effects');
})
.scan(function(acc,curr) {
console.log('Curr', curr);
return acc + curr;
{ prop : ‘a’ }
{ prop : ‘a’, prop2 : ‘b’ }
1
3
6
Operators
transformation
Switch map,
complete something based on a condition
breakCondition = Rx.Observable.fromEvent(document,'click');
breakCondition.switchMap( function(val){
return Rx.Observable.interval(3000).mapTo('Do this if nothing breaks me');
})
breakCondition.subscribe( function(val){
console.log('Switch map', val);
})
Intended action is completed/restarted
by ‘breakCondition’
var sourceTiming = timingBreakCondition.switchMap( function(val){
return Rx.Observable.interval(1000).map(function(val){
return 'Emitting' + (val + 1);
})
})
sourceTiming.subscribe(function(val){
console.log('Switch map timer', val);
})
Operators
transformation
Emits 1,2 until it is restarted by
outer timer
Switch map
var timingBreakCondition = Rx.Observable.interval(3000);
Operators
transformation
var breakCondition = Rx.Observable.fromEvent(document,'click');
var source = breakCondition.switchMap( function(val){
return Rx.Observable.interval(3000).take(1)
.flatMap(function(){
return Rx.DOM.getJSON( 'data3.json' );
});
})
source.subscribe( function(val){
console.log('Switch map', val);
})
Get data every 3 second unless a ‘click’ happens
Switch map
Same example but do something useful like fetch data
flatMap
Takes an array of observables and
merges these into one meta stream
var stream= Rx.Observable
.fromArray([1,2,3,4])
.take(2)
.flatMap(function(val){
return Rx.Observable.interval(500).map(function(){
return val;
});
});
stream.subscribe(function(val){
console.log( val );
});
Creates observables
Will emit 1,2 in eternity
Operators
transformation
flatMap + json
var source = Rx.DOM.getJSON( 'data2.json' )
.flatMap( function(data) {
return Rx.Observable.fromArray( data ).map(function(row){
return row.props.name;
});
} );
source.subscribe( function(data){
console.log( data );
}) Takes array response
and emits it row by row
.flatMap( function(data) {
return Rx.Observable.fromArray( data ).pluck('props','name');
} );
.flatMap(Rx.Observable.fromArray).pluck('props','name')
Operators
transformation
1
2
3
Excellent to use when coming from
one stream to another
Operators
transformation
flatMap - example 2
flatmapExample = Rx.Observable.fromEvent(input,'keyup')
.map( function(ev){
return ev.target.value;
})
.filter(function(text){
return text.length >=3;
})
.distinctUntilChanged()
.flatMap( function(val){
return Rx.DOM.getJSON( 'data3.json' );
})
flatmapExample.subscribe( function(result){
console.log('Flatmap', result);
})
Transform event to char
Wait until we have 3 chars
Only perform search if this ‘search’ is unique
Error scenarios
Capture error in .subscribe()
Error handling catch
var errStream = Rx.Observable.throw('Error');
var stream = Rx.Observable.create(function(observer){
observer.onNext(1);
})
var merged = Rx.Observable
.merge( errStream, stream )
merged.subscribe( function(val){
console.log('Val', val);
}, function(err){
console.log('Err', err);
}, function(){
console.log('completed');
})
Captured here but sequence
interrupted,
completed NOT reached
Capture error in .subscribe() + completed stream
Error handling
Error handling improved catch
var errStream = Rx.Observable.throw('Error');
var stream = Rx.Observable.create(function(observer){
observer.onNext(1);
})
var merged = Rx.Observable
.merge( errStream, stream )
.catch(function(err){
return Rx.Observable.of(err);
});
merged.subscribe( function(val){
console.log('Val', val);
}, function(err){
console.log('Err', err);
}, function(){
console.log('completed');
})
Captured here but sequence
interrupted,
completed IS reached
stream not processed though
can we improve it?
Wrap error stream before merging with other streams
so we don’t kill other valid streams
Error handling
Error handling
ignoring
We need to handle the erroring stream better
From
var errStream = Rx.Observable
.throw('AAA thump..')
To
var errStream = Rx.Observable
.throw('AAA thump..')
.catch(function(err){
return Rx.Observable.of(err);
});
This will emit all values and the wrapped error
Process all values and errors by wrapping the errors,
everything gets processed
Error handling
Error - ignoring
other scenario
var merged = Rx.Observable
.merge( errStream2, stream )
merged.subscribe( function(val){
console.log('Val', val);
}, function(err){
console.log('Err', err);
}, function(){
console.log('completed');
})
1,1,2
var errStream2 = Rx.Observable
.interval(200)
.take(3)
.select(function(val){
if(val === 0) {
return Rx.Observable.throw('Error stream');
} else {
return Rx.Observable.of(val);
}
})
.select(function(observable){
return observable.catch(Rx.Observable.return('Error handled'));
})
.selectMany( function(x){
return x;
});
wrap
catch and rewrite
Set a policy for error handling of streams when merging so
successful stream survive
Error handling
Error - ignoring
other scenario
You have several sources and two terminates
You want the other normal source to work
var errStream = Rx.Observable
.throw('AAA thump..');
var errStreamWithFlattenedData = Rx.Observable
.interval(500)
.take(3)
.flatMap( function(val){
if( val === 1 ) {
return Rx.Observable.throw('crashing');
}
else {
return Rx.Observable.return(val);
}
})
var normalStream = Rx.Observable.return('anything');
var handledErrorStream =
Rx.Observable.onErrorResumeNext( errStream,
normalStream, errStreamWithFlattenedData );
handledErrorStream.subscribe(function(err){
console.log('error stream ignored', err);
},
function(err){
console.log("error stream ignored, error",err);
}, function(){
console.log("completion of error stream ignored");
})
Dies midstream though,
you probably want to handle it fully
Error - Retrying
var stream = Rx.DOM.get('/products.json').retry(5);
stream.subscribe((val) => {
console.log('Data', val);
}, err => console.log(err));
Good thing with a shaky connection
5 attemps are made until it comes as an error
Subject
Observer Observable
Subject
Inherits from both
the subject can act as a proxy for a group of subscribers and a source
Subject
example
var subject = new Rx.Subject();
subject.subscribe((val) => {
console.log( 'Produced by subject', val );
});
subject.onNext(1);
subject.onCompleted();
function Producer(){
this.i = 0;
}
Producer.prototype.nextValue = function(){
return i++;
}
var observable = new Rx.Observable((observer) => {
var producer = new Producer();
observer.onNext(producer.nextValue());
observer.onCompleted();
});
observable.subscribe( (val) => {
console.log('Normal observable')
});
Bold is usually an operator like
.of() or .interval()
Acts like a observer
Acts like an observable
Subject
var subject = new Rx.Subject();
var source = Rx.Observable.interval(500);
source.subscribe(subject);
subject.subscribe(
(val) => {
console.log('Sub', val);
},
(err) => console.log(err),
() => console.log('completed')
);
setTimeout(function() {
subject.onCompleted();
}, 3000);
Pass subject as an observer
Receives all the values pushed out by the source
Able to stop receiving values
Subject
proxy one stream and add to it
var subject = new Rx.Subject();
var source = Rx.Observable.interval(500).take(3);
source.subscribe( subject );
subject.subscribe((val) => {
console.log('Subject', val);
});
subject.onNext('Mess1');
subject.onNext('Mess2');
setTimeout(function() {
subject.onCompleted();
}, 1600);
Listens to all values from source
Add to stream
Order important
Subject
different types
AsyncSubject
Returns a single value IF it completes
Cached forever
Good for ajax requests
BehaviorSubject
Receives last emitted value
and then all subsequent ones
Good for a placeholder
then real data to replace it scenario
var subject = Rx.ReplaySubject();
subject.onNext(1);
subject.subscribe((val) = > {
console.log('Replay', val);
})
subject.onNext(2);
subject.onNext(3);
var subject = Rx.Subject();
subject.onNext(1);
subject.subscribe((val) = > {
console.log('Replay', val);
})
subject.onNext(2);
subject.onNext(3);
Subject
different types
Normal subject, everything before
subscribe is lost
Replay subject, nothing is lost
Schedulers
bending time
Schedulers
Is an operator async or sync?
Give you fine grained control over how an observable emits notifications
Does it block the event loop?
Can I control how notifications are emitted?
Scheduler
bend it like beckham
Switch from Rx.Scheduler.currentThread to Rx.Scheduler.default
var stream = Rx.Observable.of(1,2,3,4,5);
var now = new Date().getTime();
stream.subscribe(
(val) => {
console.log('Current thread')
},
err => {},
() => {
var done = new Date().getTime();
console.log( (done - now) + "ms" );
})
5ms
ar defaultStream = Rx.Observable.from([1,2,3,4,5],null,null,
Rx.Scheduler.default);
defaultStream.subscribe((val) => {
console.log('Default', val);
},
err => {},
() => {
var done = Date.now();
console.log( "default " + (done - now) + "ms" );
})
console.log('default');
This happens first
default is async 143ms !!
Scheduler
Use the right scheduler for the right things
Constant Time Operations => Rx.Scheduler.immediate
Tail Recursive Operations =>Rx.Scheduler.immediate
Iteration Operations => Rx.Scheduler.currentThread
Time-based Operations => Rx.Scheduler.default
Asynchronous Conversions => Rx.Scheduler.default
Historical Data Operations => Rx.HistoricalScheduler
Unit Testing => Rx.TestScheduler
Used right it can improve performance,
used wrong you will kill your app :)
Schedulers
testing
Because scheduler has its own virtual clock
Anything scheduled on that scheduler
will adhere to time denoted on the clock
I.e we can bend time for ex unit testing
Schedulers
testingvar onNext = Rx.ReactiveTest.onNext;
var scheduler = new Rx.TestScheduler();
var subject = scheduler.createColdObservable(
onNext(100,'first'),
onNext(200,'second')
);
var result;
subject.subscribe((val) => {
result = val;
});
scheduler.advanceBy( 100 );
console.log('Should equal', result === 'first');
scheduler.advanceBy( 100 );
console.log('Should equal', result === 'second');
What happens at what intervals
Advance time
Assert
Advance time
Assert
Schedulers
testing
var testScheduler = new Rx.TestScheduler();
var stream = Rx.Observable.interval(1000, testScheduler)
.take(5)
.map((val) => {
return val + 1
})
.filter((i) => {
return i % 2 === 0
});
var result;
stream.subscribe((val) => result = val );
console.log('testing function’);
testScheduler.advanceBy(1000);
testScheduler.advanceBy(1000);
testScheduler.advanceBy(1000);
console.log('Should equal', result === 2);
testScheduler.advanceBy(1000);
testScheduler.advanceBy(1000);
console.log('Should equal', result === 4);
We decide how fast time passes
Recipes
Buffer recipe, record interactions on UI
draw where the mouse has been
Replay a game, how a character have moved
left, right, jump, duck
Idea for a project, game where you get to play til you die
and take away move that kills you
Further reading
https://xgrommx.github.io/rx-book
http://www.learnrxjs.io/
Thank you

Más contenido relacionado

La actualidad más candente

TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript IntroductionDmitry Sheiko
 
Angular - Chapter 7 - HTTP Services
Angular - Chapter 7 - HTTP ServicesAngular - Chapter 7 - HTTP Services
Angular - Chapter 7 - HTTP ServicesWebStackAcademy
 
Type script - advanced usage and practices
Type script  - advanced usage and practicesType script  - advanced usage and practices
Type script - advanced usage and practicesIwan van der Kleijn
 
Why TypeScript?
Why TypeScript?Why TypeScript?
Why TypeScript?FITC
 
Introduction for Master Class "Amazing Reactive Forms"
Introduction for Master Class "Amazing Reactive Forms"Introduction for Master Class "Amazing Reactive Forms"
Introduction for Master Class "Amazing Reactive Forms"Fabio Biondi
 
Unit 1 - TypeScript & Introduction to Angular CLI.pptx
Unit 1 - TypeScript & Introduction to Angular CLI.pptxUnit 1 - TypeScript & Introduction to Angular CLI.pptx
Unit 1 - TypeScript & Introduction to Angular CLI.pptxMalla Reddy University
 
Build RESTful API Using Express JS
Build RESTful API Using Express JSBuild RESTful API Using Express JS
Build RESTful API Using Express JSCakra Danu Sedayu
 
The New JavaScript: ES6
The New JavaScript: ES6The New JavaScript: ES6
The New JavaScript: ES6Rob Eisenberg
 
Getting Started with NgRx (Redux) Angular
Getting Started with NgRx (Redux) AngularGetting Started with NgRx (Redux) Angular
Getting Started with NgRx (Redux) AngularGustavo Costa
 
Full Stack React Workshop [CSSC x GDSC]
Full Stack React Workshop [CSSC x GDSC]Full Stack React Workshop [CSSC x GDSC]
Full Stack React Workshop [CSSC x GDSC]GDSC UofT Mississauga
 
Asynchronous javascript
 Asynchronous javascript Asynchronous javascript
Asynchronous javascriptEman Mohamed
 
React js programming concept
React js programming conceptReact js programming concept
React js programming conceptTariqul islam
 
What is component in reactjs
What is component in reactjsWhat is component in reactjs
What is component in reactjsmanojbkalla
 
RxJS & Angular Reactive Forms @ Codemotion 2019
RxJS & Angular Reactive Forms @ Codemotion 2019RxJS & Angular Reactive Forms @ Codemotion 2019
RxJS & Angular Reactive Forms @ Codemotion 2019Fabio Biondi
 

La actualidad más candente (20)

TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript Introduction
 
Ngrx slides
Ngrx slidesNgrx slides
Ngrx slides
 
Angular - Chapter 7 - HTTP Services
Angular - Chapter 7 - HTTP ServicesAngular - Chapter 7 - HTTP Services
Angular - Chapter 7 - HTTP Services
 
TypeScript - An Introduction
TypeScript - An IntroductionTypeScript - An Introduction
TypeScript - An Introduction
 
Type script - advanced usage and practices
Type script  - advanced usage and practicesType script  - advanced usage and practices
Type script - advanced usage and practices
 
Why TypeScript?
Why TypeScript?Why TypeScript?
Why TypeScript?
 
Introduction for Master Class "Amazing Reactive Forms"
Introduction for Master Class "Amazing Reactive Forms"Introduction for Master Class "Amazing Reactive Forms"
Introduction for Master Class "Amazing Reactive Forms"
 
Unit 1 - TypeScript & Introduction to Angular CLI.pptx
Unit 1 - TypeScript & Introduction to Angular CLI.pptxUnit 1 - TypeScript & Introduction to Angular CLI.pptx
Unit 1 - TypeScript & Introduction to Angular CLI.pptx
 
Build RESTful API Using Express JS
Build RESTful API Using Express JSBuild RESTful API Using Express JS
Build RESTful API Using Express JS
 
The New JavaScript: ES6
The New JavaScript: ES6The New JavaScript: ES6
The New JavaScript: ES6
 
Getting Started with NgRx (Redux) Angular
Getting Started with NgRx (Redux) AngularGetting Started with NgRx (Redux) Angular
Getting Started with NgRx (Redux) Angular
 
Full Stack React Workshop [CSSC x GDSC]
Full Stack React Workshop [CSSC x GDSC]Full Stack React Workshop [CSSC x GDSC]
Full Stack React Workshop [CSSC x GDSC]
 
Angular 2 observables
Angular 2 observablesAngular 2 observables
Angular 2 observables
 
Asynchronous javascript
 Asynchronous javascript Asynchronous javascript
Asynchronous javascript
 
React js programming concept
React js programming conceptReact js programming concept
React js programming concept
 
Workshop 21: React Router
Workshop 21: React RouterWorkshop 21: React Router
Workshop 21: React Router
 
Introduction to Redux
Introduction to ReduxIntroduction to Redux
Introduction to Redux
 
What is component in reactjs
What is component in reactjsWhat is component in reactjs
What is component in reactjs
 
Ngrx
NgrxNgrx
Ngrx
 
RxJS & Angular Reactive Forms @ Codemotion 2019
RxJS & Angular Reactive Forms @ Codemotion 2019RxJS & Angular Reactive Forms @ Codemotion 2019
RxJS & Angular Reactive Forms @ Codemotion 2019
 

Similar a RxJs - Demystified: Observables for Async JavaScript

Functional UIs with Java 8 and Vaadin JavaOne2014
Functional UIs with Java 8 and Vaadin JavaOne2014Functional UIs with Java 8 and Vaadin JavaOne2014
Functional UIs with Java 8 and Vaadin JavaOne2014hezamu
 
Cycle.js - A functional reactive UI framework
Cycle.js - A functional reactive UI frameworkCycle.js - A functional reactive UI framework
Cycle.js - A functional reactive UI frameworkNikos Kalogridis
 
Cycle.js - Functional reactive UI framework (Nikos Kalogridis)
Cycle.js - Functional reactive UI framework (Nikos Kalogridis)Cycle.js - Functional reactive UI framework (Nikos Kalogridis)
Cycle.js - Functional reactive UI framework (Nikos Kalogridis)GreeceJS
 
Tech Talk #4 : RxJava and Using RxJava in MVP - Dương Văn Tới
Tech Talk #4 : RxJava and Using RxJava in MVP - Dương Văn TớiTech Talk #4 : RxJava and Using RxJava in MVP - Dương Văn Tới
Tech Talk #4 : RxJava and Using RxJava in MVP - Dương Văn TớiNexus FrontierTech
 
Building Scalable Stateless Applications with RxJava
Building Scalable Stateless Applications with RxJavaBuilding Scalable Stateless Applications with RxJava
Building Scalable Stateless Applications with RxJavaRick Warren
 
RxJS - The Reactive extensions for JavaScript
RxJS - The Reactive extensions for JavaScriptRxJS - The Reactive extensions for JavaScript
RxJS - The Reactive extensions for JavaScriptViliam Elischer
 
Introduction to nsubstitute
Introduction to nsubstituteIntroduction to nsubstitute
Introduction to nsubstituteSuresh Loganatha
 
ReactiveCocoa in Practice
ReactiveCocoa in PracticeReactiveCocoa in Practice
ReactiveCocoa in PracticeOutware Mobile
 
RxJS Operators - Real World Use Cases - AngularMix
RxJS Operators - Real World Use Cases - AngularMixRxJS Operators - Real World Use Cases - AngularMix
RxJS Operators - Real World Use Cases - AngularMixTracy Lee
 

Similar a RxJs - Demystified: Observables for Async JavaScript (20)

Rxjs swetugg
Rxjs swetuggRxjs swetugg
Rxjs swetugg
 
Rxjs marble-testing
Rxjs marble-testingRxjs marble-testing
Rxjs marble-testing
 
Rx – reactive extensions
Rx – reactive extensionsRx – reactive extensions
Rx – reactive extensions
 
Angular2 rxjs
Angular2 rxjsAngular2 rxjs
Angular2 rxjs
 
Rxjs ngvikings
Rxjs ngvikingsRxjs ngvikings
Rxjs ngvikings
 
Rx workshop
Rx workshopRx workshop
Rx workshop
 
Functional UIs with Java 8 and Vaadin JavaOne2014
Functional UIs with Java 8 and Vaadin JavaOne2014Functional UIs with Java 8 and Vaadin JavaOne2014
Functional UIs with Java 8 and Vaadin JavaOne2014
 
Cycle.js - A functional reactive UI framework
Cycle.js - A functional reactive UI frameworkCycle.js - A functional reactive UI framework
Cycle.js - A functional reactive UI framework
 
Cycle.js - Functional reactive UI framework (Nikos Kalogridis)
Cycle.js - Functional reactive UI framework (Nikos Kalogridis)Cycle.js - Functional reactive UI framework (Nikos Kalogridis)
Cycle.js - Functional reactive UI framework (Nikos Kalogridis)
 
Tech Talk #4 : RxJava and Using RxJava in MVP - Dương Văn Tới
Tech Talk #4 : RxJava and Using RxJava in MVP - Dương Văn TớiTech Talk #4 : RxJava and Using RxJava in MVP - Dương Văn Tới
Tech Talk #4 : RxJava and Using RxJava in MVP - Dương Văn Tới
 
Reactive x
Reactive xReactive x
Reactive x
 
Reactive Java (GeeCON 2014)
Reactive Java (GeeCON 2014)Reactive Java (GeeCON 2014)
Reactive Java (GeeCON 2014)
 
Reactive Java (33rd Degree)
Reactive Java (33rd Degree)Reactive Java (33rd Degree)
Reactive Java (33rd Degree)
 
Building Scalable Stateless Applications with RxJava
Building Scalable Stateless Applications with RxJavaBuilding Scalable Stateless Applications with RxJava
Building Scalable Stateless Applications with RxJava
 
RxJS - The Reactive extensions for JavaScript
RxJS - The Reactive extensions for JavaScriptRxJS - The Reactive extensions for JavaScript
RxJS - The Reactive extensions for JavaScript
 
Saving lives with rx java
Saving lives with rx javaSaving lives with rx java
Saving lives with rx java
 
Rx java in action
Rx java in actionRx java in action
Rx java in action
 
Introduction to nsubstitute
Introduction to nsubstituteIntroduction to nsubstitute
Introduction to nsubstitute
 
ReactiveCocoa in Practice
ReactiveCocoa in PracticeReactiveCocoa in Practice
ReactiveCocoa in Practice
 
RxJS Operators - Real World Use Cases - AngularMix
RxJS Operators - Real World Use Cases - AngularMixRxJS Operators - Real World Use Cases - AngularMix
RxJS Operators - Real World Use Cases - AngularMix
 

Más de Christoffer Noring (20)

Azure signalR
Azure signalRAzure signalR
Azure signalR
 
Game dev 101 part 3
Game dev 101 part 3Game dev 101 part 3
Game dev 101 part 3
 
Game dev 101 part 2
Game dev 101   part 2Game dev 101   part 2
Game dev 101 part 2
 
Game dev workshop
Game dev workshopGame dev workshop
Game dev workshop
 
Deploying your static web app to the Cloud
Deploying your static web app to the CloudDeploying your static web app to the Cloud
Deploying your static web app to the Cloud
 
IaaS with ARM templates for Azure
IaaS with ARM templates for AzureIaaS with ARM templates for Azure
IaaS with ARM templates for Azure
 
Learning Svelte
Learning SvelteLearning Svelte
Learning Svelte
 
Ng spain
Ng spainNg spain
Ng spain
 
Angular Schematics
Angular SchematicsAngular Schematics
Angular Schematics
 
Design thinking
Design thinkingDesign thinking
Design thinking
 
Keynote ijs
Keynote ijsKeynote ijs
Keynote ijs
 
Vue fundamentasl with Testing and Vuex
Vue fundamentasl with Testing and VuexVue fundamentasl with Testing and Vuex
Vue fundamentasl with Testing and Vuex
 
Kendoui
KendouiKendoui
Kendoui
 
Angular mix chrisnoring
Angular mix chrisnoringAngular mix chrisnoring
Angular mix chrisnoring
 
Nativescript angular
Nativescript angularNativescript angular
Nativescript angular
 
Graphql, REST and Apollo
Graphql, REST and ApolloGraphql, REST and Apollo
Graphql, REST and Apollo
 
Angular 2 introduction
Angular 2 introductionAngular 2 introduction
Angular 2 introduction
 
Rxjs vienna
Rxjs viennaRxjs vienna
Rxjs vienna
 
React lecture
React lectureReact lecture
React lecture
 
Angular modules in depth
Angular modules in depthAngular modules in depth
Angular modules in depth
 

Último

Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessPixlogix Infotech
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEarley Information Science
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 

Último (20)

Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 

RxJs - Demystified: Observables for Async JavaScript

  • 1. RxJs - demystified Christoffer Noring @chris_noring Lodash for async
  • 3. What is reactive programming? Is a programming paradigm Focuses on propagating changes without us having to explicitly specify how the propagation happens State what our code should to without having to code every line
  • 4. Functional programming Avoid mutable state Avoid side-effects Functional composition over object composition = programs with predictable outcome
  • 5. Functional over imperative var list = [ 1,2,3,4,5 ]; var newList = list.map( function(value) { return value + 1; }) Produces a new list list NOT mutated/changed but projected Functional Imperative var list = [ 1,2,3,4,5 ]; list.forEach( function(value) { value += 1; }) X number invocation changes state
  • 6. Reactive programming Async data streams Turn click events user inputs data from server callbacks into a stream One paradigm/ api to rule them all
  • 7. Observable pattern Iterative pattern Observer Observable, observable sequence = Rx pattern Emits its values in order, like an iterator, BUT pushes values as they become available Has access to a producer in an observable pattern Push-based behaviour, don’t call us, we’ll call you Consumer of an observable Like listener in observable pattern Doesn’t start streaming unless it has at least one Observer subscribed to it
  • 8. At the heart of everything is the Observable
  • 9. Promise vs Array vs Observable list .map( x = > x.prop ) .filter( x => x > 2 ) .take( 2 ) list .map( x = > x.prop ) .filter( x => x > 2 ) .take( 2 ) .subscribe( x => console.log(x), ) Array Observable Promise service.get() .then( x => console.log(x) ) ) Array like, handles async but can also - Cancelled - Retried
  • 10. Observable vs Observable pattern function Producer(){ this.listeners = []; } Producer.prototype.add = function(listener){ this.listeners.push( listener ); } Producer.prototype.notify = function(message){ this.listeners.forEach( function(listener){ listener.update( message ); }) } var stream = new Rx.Observable(function(observer) { observer.onNext('message'); }) stream.subscribe( function(val){ console.log( val ); })
  • 11. Observable is usually NOT the producer, it has access to one though var stream = new Rx.Observable(function(observer){ var producer = new Producer(); producer.nextValue( function(val){ observer.onNext( val ); }) }) function Producer(){ } Producer.prototype.nextValue = function(cb){ setTimeout(function(){ cb( 1 ); },2000); } Producer created internally = “cold observable” Also responsible for emitting value to observer
  • 13. Marble diagrams Operation Stream Other stream Resulting stream 1 2 3 4 5 1 2 3 4 5 Most operators are covered at rxmarbles.com
  • 14. Observable with error var stream = Rx.Observable.create(function(observer){ observer.onNext(1); observer.onNext(2); observer.onNext(3); observer.onError( ‘there is an error’ ) }) stream.subscribe( function(data){ console.log( data ); }, function(error) { console.error( error ); } )
  • 15. Observable with completed var stream = Rx.Observable.create(function(observer){ observer.onNext( 1 ); observer.onNext( 2 ); observer.onNext( 3 ); observer.onCompleted(); }) stream.subscribe( function(data){ console.log( data ); }, function(error){ console.error( error ); }, function(){ console.info( “completed” ); } )
  • 16. Observable cancelling var homemadeStream = Rx.Observable.create((observer) => { var i=0; var handle = setInterval(function() { observer.onNext( i++ ); }, 500); return function(){ console.log('Disposing timeout'); clearTimeout( handle ); } }); var subscription2 = homemadeStream.subscribe((val) => { console.log('Homemade val',val); }); setTimeout(function() { console.log('Cancelling homemadeStream'); subscription2.dispose(); }, 1500); Define whats to happen on dispose Calling dispose Produce values till someone calls dispose
  • 17. Observable create your own var stream = Rx.Observable.create(function(observer){ observer.onNext(1); observer.onNext(2); observer.onNext(3); }) stream.subscribe( function(data){ console.log( data ); } ) Stream 1 2 3 onNext() onNext()
  • 18. Observable wrap ajax var stream = Rx.Observable.create(function(observer){ var request = new XMLHttpRequest(); request.open( ‘GET’, ‘url’ ); request.onload = function(){ if(request.status === 200) { observer.onNext( request.response ); observer.onCompleted(); } else { observer.onError( new Error( request.statusText ) ) } } request.onerror = function(){ observer.onError( new Error(‘unknown error’) ); } request.send(); }) stream.subscribe( function(result) { console.log( result ); } ) Producer
  • 19. Operators 120+ operators Combination Conditional Creational Error handling Multicasting Filtering Transformation Utility Categories
  • 21. Cold observable = producer is not shared var cold = new Observable((observer) => { var producer = new Producer(); // have observer listen to producer here }); var producer = new Producer(); var hot = new Observable((observer) => { // have observer listen to producer here }); A producer is the source of values for your observable. Operators multicasting
  • 22. Going from hot to cold Operators multicasting var stream = Rx.Observable.interval(1000); stream.subscribe(function(val){ console.log('Subscriber 1', val); }); stream.subscribe(function(val){ console.log('Subscriber 2', val); }); By definition cold, as both subscriber start from 0,1 .. NOT shared Subscriber 1 ,0 Subscriber 2 ,0 Starts on same number
  • 23. Operators multicasting How to share? stream.subscribe(function(val){ console.log('Subscriber 1', val); }); setTimeout(function() { stream.connect(); }, 2000); setTimeout(function() { stream.subscribe(function(val){ console.log('Started after 4 sec, Subscriber 2', val); }); }, 4000); var stream = Rx.Observable.interval(1000) .publish(); Sits and wait til
  • 24. Observable, creating Rx.Observable.fromArray([ 1,2,3,4 ]) Rx.Observable.fromEvent(element, ‘event’); Rx.Observable.fromArray(eventEmitter, ‘data’, function(){}) Rx.Observable.fromNodeCallback(fs.createFile) Rx.Observable.fromCallback(obj.callback) Rx.Observable.fromPromise(promise) Rx.Observable.fromIterable(function *() { yield 20 }) Rx.Observable.range(1,3) Rx.Observable.interval(miliseconds)
  • 25. Observable common operators var stream = Rx.Observable.of(1,2,3,4,5); stream.map((val) => { return val + 1; }) .filter((val) => { return val % 3 === 0; }) Investigates every value
  • 26. Observable reducer var stream2 = Rx.Observable.of(1,2,3,4,5,6); var subscription2 = stream2.reduce((acc, curr) => { return acc + curr; }); subscription2.subscribe((val) => { console.log('Sum', val); })
  • 28. Operators utility var stream = Rx.Observable.of(1,2,3,4,5); var subscription = stream .do(function(val){ console.log('Current val', val); }) .filter(function(val){ return val % 2 === 0; }); subscription.subscribe(function(val){ console.log('Val',val); }) Echos every value without changing it, used for logging Do
  • 29. Operators utility toPromise Used to create a promise from an observable stream .filter(function(val){ return val % 2 === 0; }) .toPromise() .then( function(val){ console.log('Promise', val); }) 4 var stream = Rx.Observable.of(1,2,3,4,5); Only latest value that fulfils filter is returned
  • 30. Operators utility let stream .let( observable => observable .filter(function(x){ return x % 2 > 0; })) .take(2) .subscribe(function(val){ console.log('let', val); }) Let’s us operate on the observable. We don’t need to return what we do like with a normal operator stream .filter(function(val){ return val % 2 === 0; }) var stream = Rx.Observable.of(1,2,3,4,5);
  • 31. Operators utilityDelay, the whole sequence stream .delay(1000) .subscribe( (val) => { var newTime = new Date().getTime(); console.log('Delayed', val + " " + (newTime - time)); }) Rx.Observable.merge( Rx.Observable.of('Marco').delay(1000), Rx.Observable.of('Polo').delay(2000) ).subscribe((val) => { var newTime = new Date().getTime(); console.log('Merged Delay', val + " " + (newTime - time)); }) ….. 1 second 1 2 3 ….. 1 second Marco ….. 2 second Polo
  • 33. Operators combination concat merge var concat = Rx.Observable.concat( stream, stream2 ); var stream = Rx.Observable.fromArray([1,2,3,4]); var stream2 = Rx.Observable.fromArray([5,6,7,8]); 1, 2, 3, 4, 5, 6, 7 ,8 var merge = Rx.Observable.merge( stream, stream2 ); 1, 5, 2, 6, 3, 7, 4 ,8 first stream emits all values then remaining value streams take turn There is difference so choose wisely
  • 34. Operators combination var stream = Rx.Observable.fromArray([1,2,3,4]); var stream2 = Rx.Observable.fromArray([5,6,7,8]); var combineLatest = Rx.Observable.combineLatest( stream, stream2 ); combineLatest.subscribe( function(val) { console.log( 'combine ', val ) }) combineLatest [1,5], [2,6], [3,7], [4,8]
  • 36. Operators conditional var stream = Rx.Observable .fromArray([1,2,3,4]) .every( function(val){ return val % 2 === 0; }); false var evenStream = Rx.Observable .fromArray([2,4,8]) .every( function(val){ return val % 2 === 0 }); true Condition needs to be fulfilled on all values
  • 38. Operators filtering var debounceTime = Rx.Observable .fromEvent(button,'click') .debounce(2000); debounceTime.subscribe( function(){ console.log('mouse pressed'); }) waits x ms and returns latest emitted var debouncedStream = Rx.Observable .fromArray([1,2]) .debounce(25); debouncedStream.subscribe( function(val){ console.log('debounce stream', val ); }); returns 2 ex1 ex2 Ignores all generated mouse click events for 2 seconds
  • 39. Operators filtering var mousePressedTimer = Rx.Observable.interval(1000); mousePressedTimer .takeUntil( mouseUp ) .subscribe( function(val){ console.log('mouse up has NOT happened yet',val); }, function(err){}, function(){ console.log('condition fulfilled'); }) var mouseUp = Rx.Observable.fromEvent(button,'mouseup'); Break condition Generate numbers
  • 40. var throttle = Rx.Observable .interval( 1000 ) .throttle( 1000 ); throttle.subscribe( function(val){ console.log('Throttle', val ); }); Operators filtering Delay every value by x milliseconds Throttle 1 2 3 4 1 2
  • 42. Operators transformation var numbers = Rx.Observable.interval(1000); var bufferBy = Rx.Observable.fromEvent(document,'click'); var buffered = numbers.buffer( bufferBy ); buffered.subscribe(function(values){ console.log('Buffered',values); }); [1,2] [3,4,5,6,7] etc… Numbers are generated to a buffer until condition is met, then the buffer content is emitted Buffer
  • 43. Operators transformation var bufferTime = numbers.bufferTime(2000); bufferTime.subscribe(function(values){ console.log("Buffer time",values); }) var numbers = Rx.Observable.interval(1000); Waits x miliseconds and then emits buffer BufferTime
  • 44. var expand = Rx.Observable .of(2) .expand(function(val){ return Rx.Observable.of(1 + val); }) .take(3); expand.subscribe(function(val){ console.log('Expand',val); }) Operators transformationExpand Recursively call provided callback x times
  • 45. Operators transformation Scan var scanning = Rx.Observable .of({ prop : 'a'}, { prop2 : 'b'}) .scan((acc, curr) => Object.assign({}, acc, curr), {}); scanning.subscribe( function(val){ console.log( val ); }); Add accumulated and current var sum = Rx.Observable .of(1,2,3) .do(function(){ console.log('Create side effects'); }) .scan(function(acc,curr) { console.log('Curr', curr); return acc + curr; { prop : ‘a’ } { prop : ‘a’, prop2 : ‘b’ } 1 3 6
  • 46. Operators transformation Switch map, complete something based on a condition breakCondition = Rx.Observable.fromEvent(document,'click'); breakCondition.switchMap( function(val){ return Rx.Observable.interval(3000).mapTo('Do this if nothing breaks me'); }) breakCondition.subscribe( function(val){ console.log('Switch map', val); }) Intended action is completed/restarted by ‘breakCondition’
  • 47. var sourceTiming = timingBreakCondition.switchMap( function(val){ return Rx.Observable.interval(1000).map(function(val){ return 'Emitting' + (val + 1); }) }) sourceTiming.subscribe(function(val){ console.log('Switch map timer', val); }) Operators transformation Emits 1,2 until it is restarted by outer timer Switch map var timingBreakCondition = Rx.Observable.interval(3000);
  • 48. Operators transformation var breakCondition = Rx.Observable.fromEvent(document,'click'); var source = breakCondition.switchMap( function(val){ return Rx.Observable.interval(3000).take(1) .flatMap(function(){ return Rx.DOM.getJSON( 'data3.json' ); }); }) source.subscribe( function(val){ console.log('Switch map', val); }) Get data every 3 second unless a ‘click’ happens Switch map Same example but do something useful like fetch data
  • 49. flatMap Takes an array of observables and merges these into one meta stream var stream= Rx.Observable .fromArray([1,2,3,4]) .take(2) .flatMap(function(val){ return Rx.Observable.interval(500).map(function(){ return val; }); }); stream.subscribe(function(val){ console.log( val ); }); Creates observables Will emit 1,2 in eternity Operators transformation
  • 50. flatMap + json var source = Rx.DOM.getJSON( 'data2.json' ) .flatMap( function(data) { return Rx.Observable.fromArray( data ).map(function(row){ return row.props.name; }); } ); source.subscribe( function(data){ console.log( data ); }) Takes array response and emits it row by row .flatMap( function(data) { return Rx.Observable.fromArray( data ).pluck('props','name'); } ); .flatMap(Rx.Observable.fromArray).pluck('props','name') Operators transformation 1 2 3
  • 51. Excellent to use when coming from one stream to another Operators transformation flatMap - example 2 flatmapExample = Rx.Observable.fromEvent(input,'keyup') .map( function(ev){ return ev.target.value; }) .filter(function(text){ return text.length >=3; }) .distinctUntilChanged() .flatMap( function(val){ return Rx.DOM.getJSON( 'data3.json' ); }) flatmapExample.subscribe( function(result){ console.log('Flatmap', result); }) Transform event to char Wait until we have 3 chars Only perform search if this ‘search’ is unique
  • 52. Error scenarios Capture error in .subscribe()
  • 53. Error handling catch var errStream = Rx.Observable.throw('Error'); var stream = Rx.Observable.create(function(observer){ observer.onNext(1); }) var merged = Rx.Observable .merge( errStream, stream ) merged.subscribe( function(val){ console.log('Val', val); }, function(err){ console.log('Err', err); }, function(){ console.log('completed'); }) Captured here but sequence interrupted, completed NOT reached
  • 54. Capture error in .subscribe() + completed stream Error handling
  • 55. Error handling improved catch var errStream = Rx.Observable.throw('Error'); var stream = Rx.Observable.create(function(observer){ observer.onNext(1); }) var merged = Rx.Observable .merge( errStream, stream ) .catch(function(err){ return Rx.Observable.of(err); }); merged.subscribe( function(val){ console.log('Val', val); }, function(err){ console.log('Err', err); }, function(){ console.log('completed'); }) Captured here but sequence interrupted, completed IS reached stream not processed though can we improve it?
  • 56. Wrap error stream before merging with other streams so we don’t kill other valid streams Error handling
  • 57. Error handling ignoring We need to handle the erroring stream better From var errStream = Rx.Observable .throw('AAA thump..') To var errStream = Rx.Observable .throw('AAA thump..') .catch(function(err){ return Rx.Observable.of(err); }); This will emit all values and the wrapped error
  • 58. Process all values and errors by wrapping the errors, everything gets processed Error handling
  • 59. Error - ignoring other scenario var merged = Rx.Observable .merge( errStream2, stream ) merged.subscribe( function(val){ console.log('Val', val); }, function(err){ console.log('Err', err); }, function(){ console.log('completed'); }) 1,1,2 var errStream2 = Rx.Observable .interval(200) .take(3) .select(function(val){ if(val === 0) { return Rx.Observable.throw('Error stream'); } else { return Rx.Observable.of(val); } }) .select(function(observable){ return observable.catch(Rx.Observable.return('Error handled')); }) .selectMany( function(x){ return x; }); wrap catch and rewrite
  • 60. Set a policy for error handling of streams when merging so successful stream survive Error handling
  • 61. Error - ignoring other scenario You have several sources and two terminates You want the other normal source to work var errStream = Rx.Observable .throw('AAA thump..'); var errStreamWithFlattenedData = Rx.Observable .interval(500) .take(3) .flatMap( function(val){ if( val === 1 ) { return Rx.Observable.throw('crashing'); } else { return Rx.Observable.return(val); } }) var normalStream = Rx.Observable.return('anything'); var handledErrorStream = Rx.Observable.onErrorResumeNext( errStream, normalStream, errStreamWithFlattenedData ); handledErrorStream.subscribe(function(err){ console.log('error stream ignored', err); }, function(err){ console.log("error stream ignored, error",err); }, function(){ console.log("completion of error stream ignored"); }) Dies midstream though, you probably want to handle it fully
  • 62. Error - Retrying var stream = Rx.DOM.get('/products.json').retry(5); stream.subscribe((val) => { console.log('Data', val); }, err => console.log(err)); Good thing with a shaky connection 5 attemps are made until it comes as an error
  • 63. Subject Observer Observable Subject Inherits from both the subject can act as a proxy for a group of subscribers and a source
  • 64. Subject example var subject = new Rx.Subject(); subject.subscribe((val) => { console.log( 'Produced by subject', val ); }); subject.onNext(1); subject.onCompleted(); function Producer(){ this.i = 0; } Producer.prototype.nextValue = function(){ return i++; } var observable = new Rx.Observable((observer) => { var producer = new Producer(); observer.onNext(producer.nextValue()); observer.onCompleted(); }); observable.subscribe( (val) => { console.log('Normal observable') }); Bold is usually an operator like .of() or .interval() Acts like a observer Acts like an observable
  • 65. Subject var subject = new Rx.Subject(); var source = Rx.Observable.interval(500); source.subscribe(subject); subject.subscribe( (val) => { console.log('Sub', val); }, (err) => console.log(err), () => console.log('completed') ); setTimeout(function() { subject.onCompleted(); }, 3000); Pass subject as an observer Receives all the values pushed out by the source Able to stop receiving values
  • 66. Subject proxy one stream and add to it var subject = new Rx.Subject(); var source = Rx.Observable.interval(500).take(3); source.subscribe( subject ); subject.subscribe((val) => { console.log('Subject', val); }); subject.onNext('Mess1'); subject.onNext('Mess2'); setTimeout(function() { subject.onCompleted(); }, 1600); Listens to all values from source Add to stream Order important
  • 67. Subject different types AsyncSubject Returns a single value IF it completes Cached forever Good for ajax requests BehaviorSubject Receives last emitted value and then all subsequent ones Good for a placeholder then real data to replace it scenario
  • 68. var subject = Rx.ReplaySubject(); subject.onNext(1); subject.subscribe((val) = > { console.log('Replay', val); }) subject.onNext(2); subject.onNext(3); var subject = Rx.Subject(); subject.onNext(1); subject.subscribe((val) = > { console.log('Replay', val); }) subject.onNext(2); subject.onNext(3); Subject different types Normal subject, everything before subscribe is lost Replay subject, nothing is lost
  • 70. Schedulers Is an operator async or sync? Give you fine grained control over how an observable emits notifications Does it block the event loop? Can I control how notifications are emitted?
  • 71. Scheduler bend it like beckham Switch from Rx.Scheduler.currentThread to Rx.Scheduler.default var stream = Rx.Observable.of(1,2,3,4,5); var now = new Date().getTime(); stream.subscribe( (val) => { console.log('Current thread') }, err => {}, () => { var done = new Date().getTime(); console.log( (done - now) + "ms" ); }) 5ms ar defaultStream = Rx.Observable.from([1,2,3,4,5],null,null, Rx.Scheduler.default); defaultStream.subscribe((val) => { console.log('Default', val); }, err => {}, () => { var done = Date.now(); console.log( "default " + (done - now) + "ms" ); }) console.log('default'); This happens first default is async 143ms !!
  • 72. Scheduler Use the right scheduler for the right things Constant Time Operations => Rx.Scheduler.immediate Tail Recursive Operations =>Rx.Scheduler.immediate Iteration Operations => Rx.Scheduler.currentThread Time-based Operations => Rx.Scheduler.default Asynchronous Conversions => Rx.Scheduler.default Historical Data Operations => Rx.HistoricalScheduler Unit Testing => Rx.TestScheduler Used right it can improve performance, used wrong you will kill your app :)
  • 73. Schedulers testing Because scheduler has its own virtual clock Anything scheduled on that scheduler will adhere to time denoted on the clock I.e we can bend time for ex unit testing
  • 74. Schedulers testingvar onNext = Rx.ReactiveTest.onNext; var scheduler = new Rx.TestScheduler(); var subject = scheduler.createColdObservable( onNext(100,'first'), onNext(200,'second') ); var result; subject.subscribe((val) => { result = val; }); scheduler.advanceBy( 100 ); console.log('Should equal', result === 'first'); scheduler.advanceBy( 100 ); console.log('Should equal', result === 'second'); What happens at what intervals Advance time Assert Advance time Assert
  • 75. Schedulers testing var testScheduler = new Rx.TestScheduler(); var stream = Rx.Observable.interval(1000, testScheduler) .take(5) .map((val) => { return val + 1 }) .filter((i) => { return i % 2 === 0 }); var result; stream.subscribe((val) => result = val ); console.log('testing function’); testScheduler.advanceBy(1000); testScheduler.advanceBy(1000); testScheduler.advanceBy(1000); console.log('Should equal', result === 2); testScheduler.advanceBy(1000); testScheduler.advanceBy(1000); console.log('Should equal', result === 4); We decide how fast time passes
  • 76. Recipes Buffer recipe, record interactions on UI draw where the mouse has been Replay a game, how a character have moved left, right, jump, duck Idea for a project, game where you get to play til you die and take away move that kills you