RxJS 5RxJS 5RxJS 5RxJS 5
In-depthIn-depth
by Gerard Sans (@gerardsans)
InfoQ.com: News & Community Site
• 750,000 unique visitors/month
• Published in 4 languages (English, Chinese, Japanese and Brazilian
Portuguese)
• Post content from our QCon conferences
• News 15-20 / week
• Articles 3-4 / week
• Presentations (videos) 12-15 / week
• Interviews 2-3 / week
• Books 1 / month
Watch the video with slide
synchronization on InfoQ.com!
https://www.infoq.com/presentations/
rxjs-5
Purpose of QCon
- to empower software development by facilitating the spread of
knowledge and innovation
Strategy
- practitioner-driven conference designed for YOU: influencers of
change and innovation in your teams
- speakers and topics driving the evolution and innovation
- connecting and catalyzing the influencers and innovators
Highlights
- attended by more than 12,000 delegates since 2007
- held in 9 cities worldwide
Presented at QCon London
www.qconlondon.com
A little about meA little about me
a bit more...a bit more...
AAAAsynchronous Data Streamssynchronous Data Streamssynchronous Data Streamssynchronous Data Streams
AsynchronousAsynchronous DataData StreamsStreams
will happen some time in the future
AsynchronousAsynchronous DataData StreamsStreams
raw information
Asynchronous DataAsynchronous Data StreamsStreams
values made available over time
ExamplesExamples
1
1
2
2
3
3[ , , ]
Stream
Array
Pull vs PushPull vs Push
Pull Push
Arrays,
Generators,
Iterables
DOM Events
Promises
Observables
synchronous asynchronous
Pull ExamplePull Example
// Iterable/Iterator
let iterator = [1, 2, 3].values();
console.log(iterator.next()); // {"value":1,"done":fal
console.log(iterator.next()); // {"value":2,"done":fal
console.log(iterator.next()); // {"value":3,"done":fal
console.log(iterator.next()); // {"done":true}
for (let x of [1, 2, 3]) {
console.log(x);
}
Push ExamplesPush Examples
// DOM Events
var image = document.getElementById('avatar');
image.addEventListener('load', successHandler);
image.addEventListener('error', errorHandler);
// Promise (single value)
get('languages.json')
.then(successHandler, errorHandler);
Streams timelineStreams timeline
(Unix 3, 1973)pipes
(Node.js, 2009)streams
(Microsoft, 2009)observables
(Angular 2, 2014)observables
101 Arrays101 Arrays
Array Extras (ES5)
. (), . (), . () and . ()forEach map filter reduce
Composition
forEachforEach
var team = [
{ name: "Igor Minar", commits: 259 },
{ name: "Jeff Cross", commits: 105 },
{ name: "Brian Ford", commits: 143 }
];
for(var i=0, ii=team.length; i<ii; i+=1){
console.log(team[i].name);
}
team.forEach( member => console.log(member.name) );
// Igor Minar
// Jeff Cross
// Brian Ford
mapmap
var team = [
{ name: "Igor Minar", commits: 259 },
{ name: "Jeff Cross", commits: 105 },
{ name: "Brian Ford", commits: 143 }
];
var newTeam = [];
for(var i=0, ii=team.length; i<ii; i+=1){
newTeam.push({ name: team[i].name });
}
var onlyNames = team.map(
member => ({ name: member.name })
);
filterfilter
var team = [
{ name: "Igor Minar", commits: 259 },
{ name: "Jeff Cross", commits: 105 },
{ name: "Brian Ford", commits: 143 }
];
var onlyOver120Commits = [];
for(var i=0, ii=team.length; i<ii; i+=1){
if (team[i].commits>120) {
onlyOver120Commits.push(team[i]);
}
}
var onlyOver120Commits = team.filter(
member => member.commits>120
);
reducereduce
var team = [
{ name: "Igor Minar", commits: 259 },
{ name: "Jeff Cross", commits: 105 },
{ name: "Brian Ford", commits: 143 }
];
var total = 0; // initial value
for(var i=0, ii=team.length; i<ii; i+=1){
total = total + team[i].commits;
}
var total = team.reduce(
(total, member) => total + member.commits
, 0); // initial value
// 507
CompositionComposition
var over120Commits = x => x.commits>120;
var memberName = x => x.name;
var toUpperCase = x => x.toUpperCase();
var log = x => console.log(x);
team
.filter(over120Commits)
.map(memberName)
.map(toUpperCase)
.forEach(log);
// IGOR MINAR
// BRIAN FORD
RxJS 5RxJS 5
beta2
Main ContributorsMain Contributors
@BenLesh@AndreStaltz @_ojkwon
@trxcllnt@robwormald
Paul Taylor
//Observable constructor
let obs$ = new Observable(observer => {
try {
//pushing values
observer.next(1);
observer.next(2);
observer.next(3);
//complete stream
observer.complete();
}
catch(e) {
//error handling
observer.error(e);
}
});
ObservableObservable
Basic StreamBasic Stream
//ASCII Marble Diagram
----0----1----2----3----> Observable.interval(1000);
----1----2----3| Observable.fromArray([1,2,3]);
----# Observable.of(1,2).do(x => throw
---> is the timeline
0, 1, 2, 3 are emitted values
# is an error
| is the 'completed' signal
RxMarbles
Observable helpersObservable helpers
//Observable creation helpers
Observable.of(1); // 1|
Observable.of(1,2,3).delay(100); // ---1---2---3|
Observable.from(promise);
Observable.from(numbers$);
Observable.fromArray([1,2,3]); // ---1---2---3|
Observable.fromEvent(inputDOMElement, 'keyup');
SubscribeSubscribe
Observable.subscribe(
/* next */ x => console.log(x),
/* error */ x => console.log('#'),
/* complete */ () => console.log('|')
);
Observable.subscribe({
next: x => console.log(x),
error: x => console.log('#'),
complete: () => console.log('|')
});
Hot vs ColdHot vs Cold
Hot Cold
obs.shared() default
broadcasted pre-recorded
subscribers
synced
subscribers
not synced
UnsubscribeUnsubscribe
var subscriber = Observable.subscribe(
twit => feed.push(twit),
error => console.log(error),
() => console.log('done')
);
subscriber.unsubscribe();
OperatorsOperators
// simple operators
map(), filter(), reduce(), scan(), first(), last(), single
elementAt(), toArray(), isEmpty(), take(), skip(), startWi
// merging and joining
merge(), mergeMap(flatMap), concat(), concatMap(), switch(
switchMap(), zip()
// spliting and grouping
groupBy(), window(), partition()
// buffering
buffer(), throttle(), debounce(), sample()
SchedulersSchedulers
// Synchronous (default: Scheduler.queue)
Observable.of(1)
.subscribe({
next: (x) => console.log(x)
complete: () => console.log('3')
});
console.log('2');
// a) 1 2 3
// b) 2 1 3
// c) 1 3 2
// d) 3 2 1
SchedulersSchedulers
// Asynchronous
Observable.of(1)
.observeOn(Scheduler.asap)
.subscribe({
next: (x) => console.log(x)
complete: () => console.log('3')
});
console.log('2');
// a) 1 2 3
// b) 2 1 3
// c) 1 3 2
// d) 3 2 1
Debugging RxJSDebugging RxJS
No debugger support yet
obs.do(x => console.log(x))
Drawing a marble diagram
RxJS 5 use casesRxJS 5 use cases
Asynchronous processing
Http
Forms: controls, validation
Component events
EventEmitter
Wikipedia SearchWikipedia Search
Http (Jsonp)
Form: control (valueChanges)
Async pipe
RxJS operators
flatMap/switchMap
retryWhen
plunker
Why Observables?Why Observables?
Flexible: sync or async
Powerful operators
Less code
Want more?Want more?
RxJS 5 ( )
Wikipedia Search ( )
RxJS 5 Koans ( )
github
Reactive Extensions
plunker
plunker
Thanks!Thanks!
Watch the video with slide
synchronization on InfoQ.com!
https://www.infoq.com/presentations/
rxjs-5

RxJS 5 in Depth

  • 1.
    RxJS 5RxJS 5RxJS5RxJS 5 In-depthIn-depth by Gerard Sans (@gerardsans)
  • 2.
    InfoQ.com: News &Community Site • 750,000 unique visitors/month • Published in 4 languages (English, Chinese, Japanese and Brazilian Portuguese) • Post content from our QCon conferences • News 15-20 / week • Articles 3-4 / week • Presentations (videos) 12-15 / week • Interviews 2-3 / week • Books 1 / month Watch the video with slide synchronization on InfoQ.com! https://www.infoq.com/presentations/ rxjs-5
  • 3.
    Purpose of QCon -to empower software development by facilitating the spread of knowledge and innovation Strategy - practitioner-driven conference designed for YOU: influencers of change and innovation in your teams - speakers and topics driving the evolution and innovation - connecting and catalyzing the influencers and innovators Highlights - attended by more than 12,000 delegates since 2007 - held in 9 cities worldwide Presented at QCon London www.qconlondon.com
  • 4.
    A little aboutmeA little about me
  • 5.
    a bit more...abit more...
  • 7.
    AAAAsynchronous Data StreamssynchronousData Streamssynchronous Data Streamssynchronous Data Streams
  • 9.
  • 10.
  • 11.
    Asynchronous DataAsynchronous DataStreamsStreams values made available over time
  • 12.
  • 13.
    Pull vs PushPullvs Push Pull Push Arrays, Generators, Iterables DOM Events Promises Observables synchronous asynchronous
  • 14.
    Pull ExamplePull Example //Iterable/Iterator let iterator = [1, 2, 3].values(); console.log(iterator.next()); // {"value":1,"done":fal console.log(iterator.next()); // {"value":2,"done":fal console.log(iterator.next()); // {"value":3,"done":fal console.log(iterator.next()); // {"done":true} for (let x of [1, 2, 3]) { console.log(x); }
  • 15.
    Push ExamplesPush Examples //DOM Events var image = document.getElementById('avatar'); image.addEventListener('load', successHandler); image.addEventListener('error', errorHandler); // Promise (single value) get('languages.json') .then(successHandler, errorHandler);
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
    101 Arrays101 Arrays ArrayExtras (ES5) . (), . (), . () and . ()forEach map filter reduce Composition
  • 21.
    forEachforEach var team =[ { name: "Igor Minar", commits: 259 }, { name: "Jeff Cross", commits: 105 }, { name: "Brian Ford", commits: 143 } ]; for(var i=0, ii=team.length; i<ii; i+=1){ console.log(team[i].name); } team.forEach( member => console.log(member.name) ); // Igor Minar // Jeff Cross // Brian Ford
  • 22.
    mapmap var team =[ { name: "Igor Minar", commits: 259 }, { name: "Jeff Cross", commits: 105 }, { name: "Brian Ford", commits: 143 } ]; var newTeam = []; for(var i=0, ii=team.length; i<ii; i+=1){ newTeam.push({ name: team[i].name }); } var onlyNames = team.map( member => ({ name: member.name }) );
  • 23.
    filterfilter var team =[ { name: "Igor Minar", commits: 259 }, { name: "Jeff Cross", commits: 105 }, { name: "Brian Ford", commits: 143 } ]; var onlyOver120Commits = []; for(var i=0, ii=team.length; i<ii; i+=1){ if (team[i].commits>120) { onlyOver120Commits.push(team[i]); } } var onlyOver120Commits = team.filter( member => member.commits>120 );
  • 24.
    reducereduce var team =[ { name: "Igor Minar", commits: 259 }, { name: "Jeff Cross", commits: 105 }, { name: "Brian Ford", commits: 143 } ]; var total = 0; // initial value for(var i=0, ii=team.length; i<ii; i+=1){ total = total + team[i].commits; } var total = team.reduce( (total, member) => total + member.commits , 0); // initial value // 507
  • 25.
    CompositionComposition var over120Commits =x => x.commits>120; var memberName = x => x.name; var toUpperCase = x => x.toUpperCase(); var log = x => console.log(x); team .filter(over120Commits) .map(memberName) .map(toUpperCase) .forEach(log); // IGOR MINAR // BRIAN FORD
  • 27.
  • 28.
    Main ContributorsMain Contributors @BenLesh@AndreStaltz@_ojkwon @trxcllnt@robwormald Paul Taylor
  • 29.
    //Observable constructor let obs$= new Observable(observer => { try { //pushing values observer.next(1); observer.next(2); observer.next(3); //complete stream observer.complete(); } catch(e) { //error handling observer.error(e); } }); ObservableObservable
  • 30.
    Basic StreamBasic Stream //ASCIIMarble Diagram ----0----1----2----3----> Observable.interval(1000); ----1----2----3| Observable.fromArray([1,2,3]); ----# Observable.of(1,2).do(x => throw ---> is the timeline 0, 1, 2, 3 are emitted values # is an error | is the 'completed' signal RxMarbles
  • 31.
    Observable helpersObservable helpers //Observablecreation helpers Observable.of(1); // 1| Observable.of(1,2,3).delay(100); // ---1---2---3| Observable.from(promise); Observable.from(numbers$); Observable.fromArray([1,2,3]); // ---1---2---3| Observable.fromEvent(inputDOMElement, 'keyup');
  • 32.
    SubscribeSubscribe Observable.subscribe( /* next */x => console.log(x), /* error */ x => console.log('#'), /* complete */ () => console.log('|') ); Observable.subscribe({ next: x => console.log(x), error: x => console.log('#'), complete: () => console.log('|') });
  • 33.
    Hot vs ColdHotvs Cold Hot Cold obs.shared() default broadcasted pre-recorded subscribers synced subscribers not synced
  • 34.
    UnsubscribeUnsubscribe var subscriber =Observable.subscribe( twit => feed.push(twit), error => console.log(error), () => console.log('done') ); subscriber.unsubscribe();
  • 35.
    OperatorsOperators // simple operators map(),filter(), reduce(), scan(), first(), last(), single elementAt(), toArray(), isEmpty(), take(), skip(), startWi // merging and joining merge(), mergeMap(flatMap), concat(), concatMap(), switch( switchMap(), zip() // spliting and grouping groupBy(), window(), partition() // buffering buffer(), throttle(), debounce(), sample()
  • 37.
    SchedulersSchedulers // Synchronous (default:Scheduler.queue) Observable.of(1) .subscribe({ next: (x) => console.log(x) complete: () => console.log('3') }); console.log('2'); // a) 1 2 3 // b) 2 1 3 // c) 1 3 2 // d) 3 2 1
  • 38.
    SchedulersSchedulers // Asynchronous Observable.of(1) .observeOn(Scheduler.asap) .subscribe({ next: (x)=> console.log(x) complete: () => console.log('3') }); console.log('2'); // a) 1 2 3 // b) 2 1 3 // c) 1 3 2 // d) 3 2 1
  • 40.
    Debugging RxJSDebugging RxJS Nodebugger support yet obs.do(x => console.log(x)) Drawing a marble diagram
  • 41.
    RxJS 5 usecasesRxJS 5 use cases Asynchronous processing Http Forms: controls, validation Component events EventEmitter
  • 42.
    Wikipedia SearchWikipedia Search Http(Jsonp) Form: control (valueChanges) Async pipe RxJS operators flatMap/switchMap retryWhen plunker
  • 43.
    Why Observables?Why Observables? Flexible:sync or async Powerful operators Less code
  • 45.
    Want more?Want more? RxJS5 ( ) Wikipedia Search ( ) RxJS 5 Koans ( ) github Reactive Extensions plunker plunker
  • 46.
  • 47.
    Watch the videowith slide synchronization on InfoQ.com! https://www.infoq.com/presentations/ rxjs-5