KEMBAR78
Angular2 rxjs | PPTX
Rxjs for angular 2
christoffer noring
google developer expert
In the beginning
There was callback hell
Unreadable
Angular 1 and promises
We got more ordered code with constructs like
get()
.then( doSomething )
.then( somethingElse )
.then( lastAction )
.catch( catchAll )
No callback hell anymore :)
We could do stuff like
first do A
then based on As result do B
$q.when( data )
function doSomethingAsync(){
var deferred = $q.defer();
setTimeout( () => {
if(someCondition) {
deferred.resolve( data )
} else {
deferred.reject( err );
}
},3000 )
return deferred.promise;
}
OR
We could wrap up async code in a nice way
doSomethingAsync().then((data) => {
console.log(data);
}, (err) => {
console.log(err);
})
Use this one1
2
function doAsync(){
new Promise( (resolve, reject) => {
setTimeout({
resolve(data);
},3000);
})
}
doAsync()
.then((data) => {
},
err => {
})
Or we could use native promises
Promise.all( get(), getMore().. )
Everything was great or?
Issues with promises
Not cancellable
We need to write a lot of code to retry our logic,
becomes messy
Only returns one value
Not easy to compose with other things like
callbacks and event etc,
although them being async in their nature
Cumbersome to retry
A better way, observables
stream of values over time
1 2 3 4 5
time
6
Enter observables
var stream = new Rx.Observable.create(
fnSuccess,
fnError,
fnCompleted
)
stream.subscribe((data) => {
console.log( “Data”,data );
})
nothing happens till someone subscribes
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 ); }
)
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
with completion
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 );
}
});
Observable
with cancellation
var subscription2 = homemadeStream.subscribe((val) => {
console.log('Homemade val',val);
});
setTimeout(function() {
console.log('Cancelling homemadeStream');
subscription2.dispose();
}, 1500);
we clean up
no more values are emitted
.unsubscribe()
Wrapping something into an
observer
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();
})
1
2
3
3
stream.subscribe(
(result) => { console.log( resu
err => {}
() => {})
1
3
2
Everything is a stream
You an combine async
concepts
click events
user inputs
data from server
callbacks
socket
You can create observable by hand
but is more likely to create them from something
Different ways to
create an observable
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.range(1,3)
Rx.Observable.interval(miliseconds)
Operators
gives observable their power
var stream = Rx.Observable
.interval(500)
.take(5)
.filter((val) = > {
return val % 2 === 0;
})
.map((val) => {
return “val” + 1;
})
Operators
stream.subscribe(() => {
})
operator is a function that
returns an observable
emit value every 500 ms
limit number of values
operator:
change the value
operator:
only emit certain values
Wait, it looks like
loadash?
Comparison
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),
)
service.get()
.then( x => console.log(x) )
)
Array like,
handles async
but can also
- Cancelled
- Retried
lodash/array functions
async
observable
Operators
overview
120+ operators ( 60+ Rxjs5 )
Combination
Conditional
Creational
Error handling
Filtering
Transformation
Utility
Categories
How am I gonna keep track of all that?
Use the most common ones,
and then expand your knowledge
Look at marble diagrams which one you need
Also create your own to help you in the coding process
Stream
Other stream
Resulting stream
1
Most operators are covered at rxmarbles.com
2 3
4 5
1 2 3 4 5
Marble diagrams
stream/s + operation = new stream
operation by the operator
Start with these operators
map
filter
flatMap
switchMap
do
merge
of
interval
take
of
Rx.Observable
.of(1,2,3,4)
.subscribe((val) => {
console.log( val )
})
Emits exactly whats in there
Good for prototyping an idea
map
Rx.Observable
.of(1,2,3)
.map((val) => {
return “” + val;
})
Point is to take each value,
change it
and return a new value in its place
filter
Rx.Observable
.of(1,2,3)
.filter((val) => {
return val % 2 === 0;
})
.
Point is to reduce the number of values
flatMap
Rx.Observable
.of(1,2,3)
.map( (val) => {
} )
return Rx.DOM.getJSON( ‘data’ + val +‘.json' )
Becomes a list of observables, hard to work with
Rx.Observable
.of(1,2,3)
.flatMap( (val) => {
} ) return Rx.DOM.getJSON( ‘data’ + val +‘.json' )
Flatten all observables to a meta stream
flatMap - example 2, auto
complete
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
flatMap
pe of streams and wants it to become something completely else like a strea
clicks ajax persons
Also avoid this
ajax
clicks
ajax
ajax
Subscribe
Subscribe
Subscribe
Instead become
ajax
clicks
ajax
ajax
ajax personsflat map
map
one subscribe
switchMap
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);
})
do
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
concat/merge
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
Needs queue Scheduler in Rxjs5
Other useful operators
Delay,
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));
})
Delay
….. 1 second
1
2
3
….. 1 second
Marco
….. 2 second
Polo
Debounce
var debounceTime = Rx.Observable
.fromEvent(button,'click')
.debounce(2000);
debounceTime.subscribe( function(){
console.log('mouse pressed');
})
Ignores all generated
mouse click events
for 2 seconds
click click click click click
ignore ignore ignore ignore use
…. 2 seconds passed
Fetching data
with fetch api and promise
fetch(‘data.json',init)
.then(function(response) {
return response.blob();
})
var init = { method: 'GET',
headers: myHeaders,
mode: 'cors',
cache: 'default' };
There is always this one if you don’t want to use Observables
Angular 2 and rxjs
router, most actions are observables
http lib is observables
What about angular 2 and rxjs,
how is it used?
Fetching data
with Observable
getAll() {
return http.get(`${baseUrl}`/people, {})
.map( mapPeople )
}
getAll().subscribe((people) => {
console.log(‘people’, people);
})
.catch((err) => {
console.log(‘Error’, err);
})
mapPeople(response:Response) {
return response.json().results.map(toPerson)
}
fetch data, map result, handle error
Fetch data Observable
cancelling
var stream = getAll() {
return http.get(`${baseUrl}`/people, {})
.map( mapPeople )
}
setTimeout(() => {
stream.dispose();
},3000);
stream.subscribe((data) => {
})
unsubscribe() in rxjs5
BUT we can cancel!!
Fetch data Observable
retry
var stream = Rx.DOM.get('/products.json').retry(5);
stream.subscribe((val) => {
console.log('Data', val);
}, err => console.log(err));
5 failed attempts then we hit error callback
Its so easy to retry, imagine how messy this code would be with a promise
Subject
Observer Observable
Subject
Inherits from both
the subject can act as a proxy for a group of subsc
var subject = new Rx.Subject();
subject.subscribe((val) => {
console.log( 'Produced by subject', val );
});
subject.onNext(1);
subject.onCompleted();
Acts like an 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
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
onNext() before
subscribe is lost
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);
Normal subject, everything before
subscribe is lost
Replay subject, nothing is lost
Subject - types
BehaviourSubject
Good for default values
/* Initialize with initial value of 42 */
var subject = new Rx.BehaviorSubject(42);
var subscription = subject.subscribe(
function (x) {
console.log('Next: ' + x.toString());
},
function (err) {
console.log('Error: ' + err);
},
function () {
console.log('Completed');
});
subject.onNext(56);
subject.onCompleted();
// => Completed
Init/Default value
Next: 42
Next: 56
Angular 2 with rxjs
Rxjs is a big library, if you just have request/reponse
then do
import 'rxjs/add/operator/map';
One import per used operator
import * as Rx from 'rxjs/Rx';
imports the whole of Rxjs !!!,
GOOD for development
BAD for production Then carry on coding
1
1a
Component to Component
You want something that can produce value,
that you can listen to
this.subject = new Rx.Subject();
function sendData(data){
this.subject.next( data )
}
function getSubject(){
return this.subject;
}
//service impl
Component1
Component1
service.getSubject().subscribe(()=>{})
service.sendData( data )
BUT, can be made nicer with a uniform data flow
Angular 2 rxjs setup
ngOnInit(){
this.subscription = this.service.getData();
}
ngOnDestroy(){
this.subscription.unsubscribe();
}
Setup
Teardown
life cycle hooks
Angular 2
So when to use it?
Its a better promise
Cancelling
Retry
Want to combine callbacks, event and data fetch?
Less code with rxjs
there is a forkJoin operator that replace Promise.all() etc
anything you
can do, I can do
better
no you
can’t :(
Observable Promise
Testing
Solution : bending time with schedulers
Hard to test right?
Some methods might take minutes?
Schedulers
bending time
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
var 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');
Advance time
Assert
Advance time
Assert
create observable
from scheduler
emit values
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);
replace default scheduler
0 1 2
Error scenarios
Capture error in .subscribe()
Error handling
catchvar 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(obs
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?
stream killed by errStream
:(
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");
})
Ensure good streams survive in a merge of failing streams, on
Further reading
https://xgrommx.github.io/rx-book
http://www.learnrxjs.io/
bacon.js
Thank you

Angular2 rxjs

  • 1.
    Rxjs for angular2 christoffer noring google developer expert
  • 2.
    In the beginning Therewas callback hell Unreadable
  • 3.
    Angular 1 andpromises We got more ordered code with constructs like get() .then( doSomething ) .then( somethingElse ) .then( lastAction ) .catch( catchAll ) No callback hell anymore :) We could do stuff like first do A then based on As result do B
  • 4.
    $q.when( data ) functiondoSomethingAsync(){ var deferred = $q.defer(); setTimeout( () => { if(someCondition) { deferred.resolve( data ) } else { deferred.reject( err ); } },3000 ) return deferred.promise; } OR We could wrap up async code in a nice way doSomethingAsync().then((data) => { console.log(data); }, (err) => { console.log(err); }) Use this one1 2
  • 5.
    function doAsync(){ new Promise((resolve, reject) => { setTimeout({ resolve(data); },3000); }) } doAsync() .then((data) => { }, err => { }) Or we could use native promises Promise.all( get(), getMore().. )
  • 6.
  • 7.
    Issues with promises Notcancellable We need to write a lot of code to retry our logic, becomes messy Only returns one value Not easy to compose with other things like callbacks and event etc, although them being async in their nature Cumbersome to retry
  • 8.
    A better way,observables stream of values over time 1 2 3 4 5 time 6
  • 9.
    Enter observables var stream= new Rx.Observable.create( fnSuccess, fnError, fnCompleted ) stream.subscribe((data) => { console.log( “Data”,data ); }) nothing happens till someone subscribes
  • 10.
    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 ); } )
  • 11.
    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 with completion
  • 12.
    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 ); } }); Observable with cancellation var subscription2 = homemadeStream.subscribe((val) => { console.log('Homemade val',val); }); setTimeout(function() { console.log('Cancelling homemadeStream'); subscription2.dispose(); }, 1500); we clean up no more values are emitted .unsubscribe()
  • 13.
    Wrapping something intoan observer 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(); }) 1 2 3 3 stream.subscribe( (result) => { console.log( resu err => {} () => {}) 1 3 2
  • 14.
  • 15.
    You an combineasync concepts click events user inputs data from server callbacks socket
  • 16.
    You can createobservable by hand but is more likely to create them from something
  • 17.
    Different ways to createan observable 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.range(1,3) Rx.Observable.interval(miliseconds)
  • 18.
  • 19.
    var stream =Rx.Observable .interval(500) .take(5) .filter((val) = > { return val % 2 === 0; }) .map((val) => { return “val” + 1; }) Operators stream.subscribe(() => { }) operator is a function that returns an observable emit value every 500 ms limit number of values operator: change the value operator: only emit certain values
  • 20.
    Wait, it lookslike loadash?
  • 21.
    Comparison 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), ) service.get() .then( x => console.log(x) ) ) Array like, handles async but can also - Cancelled - Retried lodash/array functions async observable
  • 22.
    Operators overview 120+ operators (60+ Rxjs5 ) Combination Conditional Creational Error handling Filtering Transformation Utility Categories
  • 23.
    How am Igonna keep track of all that? Use the most common ones, and then expand your knowledge Look at marble diagrams which one you need Also create your own to help you in the coding process
  • 24.
    Stream Other stream Resulting stream 1 Mostoperators are covered at rxmarbles.com 2 3 4 5 1 2 3 4 5 Marble diagrams stream/s + operation = new stream operation by the operator
  • 25.
    Start with theseoperators map filter flatMap switchMap do merge of interval take
  • 26.
    of Rx.Observable .of(1,2,3,4) .subscribe((val) => { console.log(val ) }) Emits exactly whats in there Good for prototyping an idea
  • 27.
    map Rx.Observable .of(1,2,3) .map((val) => { return“” + val; }) Point is to take each value, change it and return a new value in its place
  • 28.
    filter Rx.Observable .of(1,2,3) .filter((val) => { returnval % 2 === 0; }) . Point is to reduce the number of values
  • 29.
    flatMap Rx.Observable .of(1,2,3) .map( (val) =>{ } ) return Rx.DOM.getJSON( ‘data’ + val +‘.json' ) Becomes a list of observables, hard to work with Rx.Observable .of(1,2,3) .flatMap( (val) => { } ) return Rx.DOM.getJSON( ‘data’ + val +‘.json' ) Flatten all observables to a meta stream
  • 30.
    flatMap - example2, auto complete 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
  • 31.
    flatMap pe of streamsand wants it to become something completely else like a strea clicks ajax persons Also avoid this ajax clicks ajax ajax Subscribe Subscribe Subscribe Instead become ajax clicks ajax ajax ajax personsflat map map one subscribe
  • 32.
    switchMap Switch map, complete somethingbased 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); })
  • 33.
    do 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
  • 34.
    concat/merge 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 Needs queue Scheduler in Rxjs5
  • 35.
  • 36.
    Delay, 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)); }) Delay ….. 1 second 1 2 3 ….. 1 second Marco ….. 2 second Polo
  • 37.
    Debounce var debounceTime =Rx.Observable .fromEvent(button,'click') .debounce(2000); debounceTime.subscribe( function(){ console.log('mouse pressed'); }) Ignores all generated mouse click events for 2 seconds click click click click click ignore ignore ignore ignore use …. 2 seconds passed
  • 38.
    Fetching data with fetchapi and promise fetch(‘data.json',init) .then(function(response) { return response.blob(); }) var init = { method: 'GET', headers: myHeaders, mode: 'cors', cache: 'default' }; There is always this one if you don’t want to use Observables
  • 39.
    Angular 2 andrxjs router, most actions are observables http lib is observables What about angular 2 and rxjs, how is it used?
  • 40.
    Fetching data with Observable getAll(){ return http.get(`${baseUrl}`/people, {}) .map( mapPeople ) } getAll().subscribe((people) => { console.log(‘people’, people); }) .catch((err) => { console.log(‘Error’, err); }) mapPeople(response:Response) { return response.json().results.map(toPerson) } fetch data, map result, handle error
  • 41.
    Fetch data Observable cancelling varstream = getAll() { return http.get(`${baseUrl}`/people, {}) .map( mapPeople ) } setTimeout(() => { stream.dispose(); },3000); stream.subscribe((data) => { }) unsubscribe() in rxjs5 BUT we can cancel!!
  • 42.
    Fetch data Observable retry varstream = Rx.DOM.get('/products.json').retry(5); stream.subscribe((val) => { console.log('Data', val); }, err => console.log(err)); 5 failed attempts then we hit error callback Its so easy to retry, imagine how messy this code would be with a promise
  • 43.
    Subject Observer Observable Subject Inherits fromboth the subject can act as a proxy for a group of subsc
  • 44.
    var subject =new Rx.Subject(); subject.subscribe((val) => { console.log( 'Produced by subject', val ); }); subject.onNext(1); subject.onCompleted(); Acts like an observer Acts like an observable Subject
  • 45.
    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
  • 46.
    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 onNext() before subscribe is lost
  • 47.
    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); Normal subject, everything before subscribe is lost Replay subject, nothing is lost Subject - types
  • 48.
    BehaviourSubject Good for defaultvalues /* Initialize with initial value of 42 */ var subject = new Rx.BehaviorSubject(42); var subscription = subject.subscribe( function (x) { console.log('Next: ' + x.toString()); }, function (err) { console.log('Error: ' + err); }, function () { console.log('Completed'); }); subject.onNext(56); subject.onCompleted(); // => Completed Init/Default value Next: 42 Next: 56
  • 49.
    Angular 2 withrxjs Rxjs is a big library, if you just have request/reponse then do import 'rxjs/add/operator/map'; One import per used operator import * as Rx from 'rxjs/Rx'; imports the whole of Rxjs !!!, GOOD for development BAD for production Then carry on coding 1 1a
  • 50.
    Component to Component Youwant something that can produce value, that you can listen to this.subject = new Rx.Subject(); function sendData(data){ this.subject.next( data ) } function getSubject(){ return this.subject; } //service impl Component1 Component1 service.getSubject().subscribe(()=>{}) service.sendData( data ) BUT, can be made nicer with a uniform data flow
  • 51.
    Angular 2 rxjssetup ngOnInit(){ this.subscription = this.service.getData(); } ngOnDestroy(){ this.subscription.unsubscribe(); } Setup Teardown life cycle hooks
  • 52.
    Angular 2 So whento use it? Its a better promise Cancelling Retry Want to combine callbacks, event and data fetch? Less code with rxjs there is a forkJoin operator that replace Promise.all() etc anything you can do, I can do better no you can’t :( Observable Promise
  • 53.
    Testing Solution : bendingtime with schedulers Hard to test right? Some methods might take minutes?
  • 54.
  • 55.
    Because scheduler hasits 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
  • 56.
    var 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'); Advance time Assert Advance time Assert create observable from scheduler emit values
  • 57.
    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); replace default scheduler 0 1 2
  • 58.
  • 59.
    Error handling catchvar 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
  • 60.
    Capture error in.subscribe() + completed stream Error handling
  • 61.
    Error handling improved catch varerrStream = Rx.Observable.throw('Error'); var stream = Rx.Observable.create(function(obs 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? stream killed by errStream :(
  • 62.
    Wrap error streambefore merging with other streams so we don’t kill other valid streams Error handling
  • 63.
    Error handling ignoring We needto 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
  • 64.
    Process all valuesand errors by wrapping the errors, everything gets processed Error handling
  • 65.
    Error - ignoring otherscenario 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
  • 66.
    Set a policyfor error handling of streams when merging so successful stream survive Error handling
  • 67.
    Error - ignoring otherscenario 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"); }) Ensure good streams survive in a merge of failing streams, on
  • 68.
  • 69.