SlideShare une entreprise Scribd logo
1  sur  44
Télécharger pour lire hors ligne
Reactive Frontends with RxJS and Angular
Sergi Almar
@sergialmar
1
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Reactive efforts in Spring
2
Spring
framework
Spring
Boot
Project
Reactor
Spring
Security
Spring
Data
Spring
Cloud
Spring
Integration
…
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Agenda
3
• RxJS
• Obervables
• Operators
• Combining observables
• Error handling
• Angular
• Managing subscriptions
• HttpClient
• Reactive Forms
• WebSockets /SSE
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 4
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Language support
5
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Async in web apps
6
• DOM Event (0-N values)
• AJAX (1 value)
• WebSocket (0-N values)
• Server Sent Event (0-N values)
• Animation (0-N values)
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Reactive programming
7
Pros
• Clean and understandable code
• Focus on the result
• Complex operations out of the box
• Abort processing of data when you don’t need it (cancel)
Cons
• More difficult to debug
• Learning curve
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 8
Observable.of(...)
Factory Methods
Observable.from(...)
Observable.fromEvent(...)
Observable.interval(...)
...
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 9
Creating an Observable
const welcome$ = Observable.create((subscriber) => {
subscriber.next('Welcome');
subscriber.next('to');
subscriber.next('S1P');
subscriber.next('!');
subscriber.complete();
});
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 10
Observer
subscribe
notification
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Observer
11
export interface Observer<T> {
closed?: boolean;
next: (value: T) => void;
error: (err: any) => void;
complete: () => void;
}
var observer = {
next: x => console.log('Next value: ' + x),
error: err => console.error('Error: ' + err),
complete: () => console.log('Complete notification')
};
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Observer
12
Observable.interval(1000) Producer
Consumer.subscribe(val => console.log(val))
.operator(...)
.operator(...)
.operator(...)
Pipeline
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Unsubscribe
13
const mouseMove$ = Observable.fromEvent(document, 'mousemove');
const subscription = mouseMove$.subscribe(console.log);
…
subscription.unsubscribe();
- Release resources allocated by the observable
- No more events sent to the registered observer
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Operators
14
create
fromEvent
range
…
Creation
map
scan
switchMap
…
Transformation
debounce
filter
take
…
Filtering
concat
merge
startWith
…
Combination
catch
retry
retryWhen
Error Handling
share
publish
multicast
Multicast
do / tap
delay
toPromise
…
Utility
every
defaultIfEmpty
Conditional
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Lettable Operators
15
<T, R>(source: Observable<T>) => Observable<R>
Observable.interval(1000)
.pipe(
filter(x => x % 2 === 0),
map(x => x * x),
take(5)
)
.subscribe(x => console.log(x))
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 16
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Combining Observables: merge
17
const spring$ =
Observable.of('spring', 'spring-boot', ‘spring-data');
const cloud$ =
Observable.of('cloud-native', 'cloudfoundry', 'bosh');
Observable.merge(spring$, cloud$).subscribe(console.log);
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 1818
Spring
Spring
spring$
cloud$
Spring
Boot
Spring
Boot
Cloud
Native
Cloud
Native
Spring
Data
Spring
Data
Cloud
Foundry
Cloud
Foundry
Bosh
Bosh
merge(spring$, cloud$)
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
switchMap
19
Observable.of(1, 2, 3)
.pipe(
switchMap(num => Observable.of(num, num * num))
).subscribe(console.log);
1
switchMap(num => Observable.of(num, num * num)
1 1
2
2 4
3
3 9
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
forkJoin
20
1
const users$ = Observable.forkJoin(
findUser(1),
findUser(2),
findUser(3)
);
...
users$.subscribe(console.log);
2
3
fork
join
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
fork
forkJoin
21
1
const users$ = Observable.forkJoin(
findUser(1),
findUser(2),
findUser(3)
);
users$.subscribe(console.log);
2 3
join
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
join
forkJoin
22
1
const users$ = Observable.forkJoin(
findUser(1),
findUser(2),
findUser(3)
);
users$.subscribe(console.log);
fork 1 2 3
2 3
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
join
forkJoin
23
1
const users$ = Observable.forkJoin(
findUser(1),
findUser(2),
findUser(3)
);
users$.subscribe(console.log);
fork
2 3[ ], ,
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Errors
24
• When an error occurs the observable is cancelled and no data passes though
• Errors are propagated to the downstream observers
Observable.range(1, 20)
.pipe(
map(num => {
if (num === 13) {
throw new Error('I don't like 13');
}
return num;
})
)
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Remember the Observer?
25
export interface Observer<T> {
closed?: boolean;
next: (value: T) => void;
error: (err: any) => void;
complete: () => void;
}
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Errors
26
• When an error occurs the observable is cancelled and no data passes though
• Errors are propagated to the downstream observers
Observable.range(1, 20)
.pipe(
map(num => {
if (num === 13) {
throw new Error('I don't like 13');
}
return num;
})
).subscribe(
num => console.log('Got num ' + num),
err => console.log('Upssss...' + err));
map
1
1
13
X
…
…
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
catchError
27
Observable.range(1, 20)
.pipe(
map(num => {
if (num === 13) {
throw new Error('I don't like 13');
}
return num;
}),
catchError(err => Observable.range(100, 3))
)
.subscribe(console.log);
Output:
1
2
3
4
5
6
7
8
9
10
11
12
100
111
112
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Angular
28
RxJS can be used with any framework
Angular has reactivity at its core, leveraging RxJS
- HttpClient
- Reactive Forms
- Router
- Component communication
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Unsubscribing
29
@Component({
selector: 'app-mouse-position',
template: '<span>{{mousePosition}}</span>'
})
export class MousePositionComponent implements OnInit, OnDestroy {
ngOnInit() {
}
ngOnDestroy() {
}
}
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Unsubscribing
30
@Component({
selector: 'app-mouse-position',
template: '<span>{{mousePosition}}</span>'
})
export class MousePositionComponent implements OnInit, OnDestroy {
ngOnInit() {
}
ngOnDestroy() {
}
}
const mouseDown$ = Observable.fromEvent(document, 'mousemove')
.pipe(
map(val => `${val.offsetX} ${val.offsetY}`)
);
Define Observable
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Unsubscribing
31
@Component({
selector: 'app-mouse-position',
template: '<span>{{mousePosition}}</span>'
})
export class MousePositionComponent implements OnInit, OnDestroy {
mousePosition: String;
mouseSubscription: Subscription;
ngOnInit() {
}
ngOnDestroy() {
}
}
this.mouseSubscription = mouseDown$
.subscribe((pos: String) => this.mousePosition = pos);
const mouseDown$ = Observable.fromEvent(document, 'mousemove')
.pipe(
map(val => `${val.offsetX} ${val.offsetY}`)
);
Subscribe
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Unsubscribing
32
@Component({
selector: 'app-mouse-position',
template: '<span>{{mousePosition}}</span>'
})
export class MousePositionComponent implements OnInit, OnDestroy {
mousePosition: String;
mouseSubscription: Subscription;
ngOnInit() {
}
ngOnDestroy() {
}
}
this.mouseSubscription = mouseDown$
.subscribe((pos: String) => this.mousePosition = pos);
const mouseDown$ = Observable.fromEvent(document, 'mousemove')
.pipe(
map(val => `${val.offsetX} ${val.offsetY}`)
);
this.mouseSubscription.unsubscribe();Unsubscribe
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Async pipe
33
@Component({
selector: 'app-mouse-position',
template: '<span>{{mousePosition$ | async}}</span>'
})
export class MousePositionComponent implements OnInit {
mousePosition$: Observable<string>;
ngOnInit() {
this.mousePosition$ = fromEvent(document, 'mousemove')
.pipe(
map(val => `${val.offsetX} ${val.offsetY}`)
);
}
}
No subscription management
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
HttpClient
34
- Simple API
- Strong typing of request
and response objects
- Support for interceptors
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
HttpClient
35
get<T>(url: string, options?: {
headers?: HttpHeaders | {
[header: string]: string | string[];
};
observe?: 'body';
params?: HttpParams | {
[param: string]: string | string[];
};
reportProgress?: boolean;
responseType?: 'json';
withCredentials?: boolean;
}): Observable<T>;
httpClient.get<User>('http://localhost:8080/user/1')
.subscribe((user: User) => console.log('User: ' + user.name));
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Retry
36
- Retry the failed stream
- Propagates the error downstream if not successful
httpClient.get<User>('http://localhost:8080/user/1')
.pipe(
retry(3)
)
httpClient.get<User>('http://localhost:8080/user/1')
.pipe(
retryWhen(errors => errors.pipe(delay(1000).take(3)))
)
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Reactive Forms
37
• Two options to build forms
• Reactive and template-driven forms
• Monitor changes by subscribing to one of the form control properties 
this.favoriteConference.valueChanges
this.favoriteConference.statusChanges
(valid / invalid)<input formControllName=“favoriteConference” ..>
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Server Sent Events
38
Wrapping an EventSource in an Observable
const eventSource$ = Observable.create(observer => {
const source = new EventSource('http://localhost:8080/search-push');
source.addEventListener('message',
event => observer.next(event));
}
);
* EventSource added in typings.d.ts
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
WebSocket
39
Wrapping a WebSocket in an Observable
const ws$ = Observable.create(observer => {
const source = new WebSocket(‘ws://localhost:8080/search-push');
source.addEventListener('message',
event => observer.next(event));
}
);
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
WebSocket
40
Wrapping a WebSocket in an Observable
ws$.subscribe(...)
new WebSocket(...)
ws$.subscribe(...)
new WebSocket(...)
ws$.subscribe(...)
new WebSocket(...)
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Subscription sharing
41
const ws$ = Observable.create(observer => {
const source = new WebSocket(‘ws://localhost:8080/search-push');
source.addEventListener('message',
event => observer.next(event));
}
)
.share();
DEMO
Putting all together
Q&A
Thank you!
@sergialmar
43
#springone@s1p
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 44

Contenu connexe

Tendances

Curious Coders Java Web Frameworks Comparison
Curious Coders Java Web Frameworks ComparisonCurious Coders Java Web Frameworks Comparison
Curious Coders Java Web Frameworks Comparison
Hamed Hatami
 

Tendances (20)

Debugging Serverless for Cloud
Debugging Serverless for CloudDebugging Serverless for Cloud
Debugging Serverless for Cloud
 
4Developers 2015: Do you think you're doing microservice architecture? - Marc...
4Developers 2015: Do you think you're doing microservice architecture? - Marc...4Developers 2015: Do you think you're doing microservice architecture? - Marc...
4Developers 2015: Do you think you're doing microservice architecture? - Marc...
 
Latency analysis for your microservices using Spring Cloud & Zipkin
Latency analysis for your microservices using Spring Cloud & ZipkinLatency analysis for your microservices using Spring Cloud & Zipkin
Latency analysis for your microservices using Spring Cloud & Zipkin
 
Secrets of Successful Digital Transformers
Secrets of Successful Digital TransformersSecrets of Successful Digital Transformers
Secrets of Successful Digital Transformers
 
Better Than BASH: Scripting Kotlin
Better Than BASH: Scripting KotlinBetter Than BASH: Scripting Kotlin
Better Than BASH: Scripting Kotlin
 
Resource Handling in Spring MVC 4.1
Resource Handling in Spring MVC 4.1Resource Handling in Spring MVC 4.1
Resource Handling in Spring MVC 4.1
 
Spring Cloud Kubernetes - Ryan Baxter
Spring Cloud Kubernetes - Ryan BaxterSpring Cloud Kubernetes - Ryan Baxter
Spring Cloud Kubernetes - Ryan Baxter
 
Consumer Driven Contracts and Your Microservice Architecture
Consumer Driven Contracts and Your Microservice ArchitectureConsumer Driven Contracts and Your Microservice Architecture
Consumer Driven Contracts and Your Microservice Architecture
 
Session State Caching with Spring
Session State Caching with SpringSession State Caching with Spring
Session State Caching with Spring
 
Front End Development for Backend Developers - GIDS 2019
Front End Development for Backend Developers - GIDS 2019Front End Development for Backend Developers - GIDS 2019
Front End Development for Backend Developers - GIDS 2019
 
Architectures That Bend but Don't Break
Architectures That Bend but Don't BreakArchitectures That Bend but Don't Break
Architectures That Bend but Don't Break
 
Seven Simple Reasons to Use AppFuse
Seven Simple Reasons to Use AppFuseSeven Simple Reasons to Use AppFuse
Seven Simple Reasons to Use AppFuse
 
Comparing JVM Web Frameworks - Rich Web Experience 2010
Comparing JVM Web Frameworks - Rich Web Experience 2010Comparing JVM Web Frameworks - Rich Web Experience 2010
Comparing JVM Web Frameworks - Rich Web Experience 2010
 
Curious Coders Java Web Frameworks Comparison
Curious Coders Java Web Frameworks ComparisonCurious Coders Java Web Frameworks Comparison
Curious Coders Java Web Frameworks Comparison
 
Numbers in the Hidden: A Pragmatic View of 'Nirvana'
Numbers in the Hidden: A Pragmatic View of 'Nirvana'Numbers in the Hidden: A Pragmatic View of 'Nirvana'
Numbers in the Hidden: A Pragmatic View of 'Nirvana'
 
Building Rich Applications with Appcelerator
Building Rich Applications with AppceleratorBuilding Rich Applications with Appcelerator
Building Rich Applications with Appcelerator
 
A Gentle Introduction to Angular Schematics - Devoxx Belgium 2019
A Gentle Introduction to Angular Schematics - Devoxx Belgium 2019A Gentle Introduction to Angular Schematics - Devoxx Belgium 2019
A Gentle Introduction to Angular Schematics - Devoxx Belgium 2019
 
P to V to C: The Value of Bringing “Everything” to Containers
P to V to C: The Value of Bringing “Everything” to ContainersP to V to C: The Value of Bringing “Everything” to Containers
P to V to C: The Value of Bringing “Everything” to Containers
 
How to Win at UI Development in the World of Microservices - THAT Conference ...
How to Win at UI Development in the World of Microservices - THAT Conference ...How to Win at UI Development in the World of Microservices - THAT Conference ...
How to Win at UI Development in the World of Microservices - THAT Conference ...
 
Spring Boot APIs and Angular Apps: Get Hip with JHipster! KCDC 2019
Spring Boot APIs and Angular Apps: Get Hip with JHipster! KCDC 2019Spring Boot APIs and Angular Apps: Get Hip with JHipster! KCDC 2019
Spring Boot APIs and Angular Apps: Get Hip with JHipster! KCDC 2019
 

Similaire à Reactive frontends with RxJS and Angular

Similaire à Reactive frontends with RxJS and Angular (20)

Reactor 3.0, a reactive foundation for java 8 and Spring
Reactor 3.0, a reactive foundation for java 8 and SpringReactor 3.0, a reactive foundation for java 8 and Spring
Reactor 3.0, a reactive foundation for java 8 and Spring
 
Cloud Native Java with Spring Cloud Services
Cloud Native Java with Spring Cloud ServicesCloud Native Java with Spring Cloud Services
Cloud Native Java with Spring Cloud Services
 
12 Factor, or Cloud Native Apps – What EXACTLY Does that Mean for Spring Deve...
12 Factor, or Cloud Native Apps – What EXACTLY Does that Mean for Spring Deve...12 Factor, or Cloud Native Apps – What EXACTLY Does that Mean for Spring Deve...
12 Factor, or Cloud Native Apps – What EXACTLY Does that Mean for Spring Deve...
 
Zuul @ Netflix SpringOne Platform
Zuul @ Netflix SpringOne PlatformZuul @ Netflix SpringOne Platform
Zuul @ Netflix SpringOne Platform
 
What's new in Reactor Californium
What's new in Reactor CaliforniumWhat's new in Reactor Californium
What's new in Reactor Californium
 
Continuous Delivery for Microservice Architectures with Concourse & Cloud Fou...
Continuous Delivery for Microservice Architectures with Concourse & Cloud Fou...Continuous Delivery for Microservice Architectures with Concourse & Cloud Fou...
Continuous Delivery for Microservice Architectures with Concourse & Cloud Fou...
 
12 Factor, or Cloud Native Apps - What EXACTLY Does that Mean for Spring Deve...
12 Factor, or Cloud Native Apps - What EXACTLY Does that Mean for Spring Deve...12 Factor, or Cloud Native Apps - What EXACTLY Does that Mean for Spring Deve...
12 Factor, or Cloud Native Apps - What EXACTLY Does that Mean for Spring Deve...
 
Core Spring + Reactive 김민석
Core Spring + Reactive  김민석Core Spring + Reactive  김민석
Core Spring + Reactive 김민석
 
Under the Hood of Reactive Data Access (2/2)
Under the Hood of Reactive Data Access (2/2)Under the Hood of Reactive Data Access (2/2)
Under the Hood of Reactive Data Access (2/2)
 
SpringOnePlatform2017 recap
SpringOnePlatform2017 recapSpringOnePlatform2017 recap
SpringOnePlatform2017 recap
 
Migrating to Angular 5 for Spring Developers
Migrating to Angular 5 for Spring DevelopersMigrating to Angular 5 for Spring Developers
Migrating to Angular 5 for Spring Developers
 
Migrating to Angular 4 for Spring Developers
Migrating to Angular 4 for Spring Developers Migrating to Angular 4 for Spring Developers
Migrating to Angular 4 for Spring Developers
 
Containers Were Never Your End State
Containers Were Never Your End StateContainers Were Never Your End State
Containers Were Never Your End State
 
Implementing microservices tracing with spring cloud and zipkin (spring one)
Implementing microservices tracing with spring cloud and zipkin (spring one)Implementing microservices tracing with spring cloud and zipkin (spring one)
Implementing microservices tracing with spring cloud and zipkin (spring one)
 
Cassandra and DataStax Enterprise on PCF
Cassandra and DataStax Enterprise on PCFCassandra and DataStax Enterprise on PCF
Cassandra and DataStax Enterprise on PCF
 
Developing Real-Time Data Pipelines with Apache Kafka
Developing Real-Time Data Pipelines with Apache KafkaDeveloping Real-Time Data Pipelines with Apache Kafka
Developing Real-Time Data Pipelines with Apache Kafka
 
Avoiding that $1M Dollar AWS Bill
Avoiding that $1M Dollar AWS BillAvoiding that $1M Dollar AWS Bill
Avoiding that $1M Dollar AWS Bill
 
Simplifying Apache Geode with Spring Data
Simplifying Apache Geode with Spring DataSimplifying Apache Geode with Spring Data
Simplifying Apache Geode with Spring Data
 
Extending the Platform with Spring Boot and Cloud Foundry
Extending the Platform with Spring Boot and Cloud FoundryExtending the Platform with Spring Boot and Cloud Foundry
Extending the Platform with Spring Boot and Cloud Foundry
 
Extending the Platform
Extending the PlatformExtending the Platform
Extending the Platform
 

Plus de VMware Tanzu

Plus de VMware Tanzu (20)

What AI Means For Your Product Strategy And What To Do About It
What AI Means For Your Product Strategy And What To Do About ItWhat AI Means For Your Product Strategy And What To Do About It
What AI Means For Your Product Strategy And What To Do About It
 
Make the Right Thing the Obvious Thing at Cardinal Health 2023
Make the Right Thing the Obvious Thing at Cardinal Health 2023Make the Right Thing the Obvious Thing at Cardinal Health 2023
Make the Right Thing the Obvious Thing at Cardinal Health 2023
 
Enhancing DevEx and Simplifying Operations at Scale
Enhancing DevEx and Simplifying Operations at ScaleEnhancing DevEx and Simplifying Operations at Scale
Enhancing DevEx and Simplifying Operations at Scale
 
Spring Update | July 2023
Spring Update | July 2023Spring Update | July 2023
Spring Update | July 2023
 
Platforms, Platform Engineering, & Platform as a Product
Platforms, Platform Engineering, & Platform as a ProductPlatforms, Platform Engineering, & Platform as a Product
Platforms, Platform Engineering, & Platform as a Product
 
Building Cloud Ready Apps
Building Cloud Ready AppsBuilding Cloud Ready Apps
Building Cloud Ready Apps
 
Spring Boot 3 And Beyond
Spring Boot 3 And BeyondSpring Boot 3 And Beyond
Spring Boot 3 And Beyond
 
Spring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdf
Spring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdfSpring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdf
Spring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdf
 
Simplify and Scale Enterprise Apps in the Cloud | Boston 2023
Simplify and Scale Enterprise Apps in the Cloud | Boston 2023Simplify and Scale Enterprise Apps in the Cloud | Boston 2023
Simplify and Scale Enterprise Apps in the Cloud | Boston 2023
 
Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023
Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023
Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023
 
tanzu_developer_connect.pptx
tanzu_developer_connect.pptxtanzu_developer_connect.pptx
tanzu_developer_connect.pptx
 
Tanzu Virtual Developer Connect Workshop - French
Tanzu Virtual Developer Connect Workshop - FrenchTanzu Virtual Developer Connect Workshop - French
Tanzu Virtual Developer Connect Workshop - French
 
Tanzu Developer Connect Workshop - English
Tanzu Developer Connect Workshop - EnglishTanzu Developer Connect Workshop - English
Tanzu Developer Connect Workshop - English
 
Virtual Developer Connect Workshop - English
Virtual Developer Connect Workshop - EnglishVirtual Developer Connect Workshop - English
Virtual Developer Connect Workshop - English
 
Tanzu Developer Connect - French
Tanzu Developer Connect - FrenchTanzu Developer Connect - French
Tanzu Developer Connect - French
 
Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023
Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023
Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023
 
SpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring Boot
SpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring BootSpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring Boot
SpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring Boot
 
SpringOne Tour: The Influential Software Engineer
SpringOne Tour: The Influential Software EngineerSpringOne Tour: The Influential Software Engineer
SpringOne Tour: The Influential Software Engineer
 
SpringOne Tour: Domain-Driven Design: Theory vs Practice
SpringOne Tour: Domain-Driven Design: Theory vs PracticeSpringOne Tour: Domain-Driven Design: Theory vs Practice
SpringOne Tour: Domain-Driven Design: Theory vs Practice
 
SpringOne Tour: Spring Recipes: A Collection of Common-Sense Solutions
SpringOne Tour: Spring Recipes: A Collection of Common-Sense SolutionsSpringOne Tour: Spring Recipes: A Collection of Common-Sense Solutions
SpringOne Tour: Spring Recipes: A Collection of Common-Sense Solutions
 

Dernier

Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 

Dernier (20)

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
 
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...
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
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
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
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
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 

Reactive frontends with RxJS and Angular

  • 1. Reactive Frontends with RxJS and Angular Sergi Almar @sergialmar 1
  • 2. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Reactive efforts in Spring 2 Spring framework Spring Boot Project Reactor Spring Security Spring Data Spring Cloud Spring Integration …
  • 3. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Agenda 3 • RxJS • Obervables • Operators • Combining observables • Error handling • Angular • Managing subscriptions • HttpClient • Reactive Forms • WebSockets /SSE
  • 4. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 4
  • 5. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Language support 5
  • 6. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Async in web apps 6 • DOM Event (0-N values) • AJAX (1 value) • WebSocket (0-N values) • Server Sent Event (0-N values) • Animation (0-N values)
  • 7. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Reactive programming 7 Pros • Clean and understandable code • Focus on the result • Complex operations out of the box • Abort processing of data when you don’t need it (cancel) Cons • More difficult to debug • Learning curve
  • 8. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 8 Observable.of(...) Factory Methods Observable.from(...) Observable.fromEvent(...) Observable.interval(...) ...
  • 9. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 9 Creating an Observable const welcome$ = Observable.create((subscriber) => { subscriber.next('Welcome'); subscriber.next('to'); subscriber.next('S1P'); subscriber.next('!'); subscriber.complete(); });
  • 10. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 10 Observer subscribe notification
  • 11. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Observer 11 export interface Observer<T> { closed?: boolean; next: (value: T) => void; error: (err: any) => void; complete: () => void; } var observer = { next: x => console.log('Next value: ' + x), error: err => console.error('Error: ' + err), complete: () => console.log('Complete notification') };
  • 12. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Observer 12 Observable.interval(1000) Producer Consumer.subscribe(val => console.log(val)) .operator(...) .operator(...) .operator(...) Pipeline
  • 13. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Unsubscribe 13 const mouseMove$ = Observable.fromEvent(document, 'mousemove'); const subscription = mouseMove$.subscribe(console.log); … subscription.unsubscribe(); - Release resources allocated by the observable - No more events sent to the registered observer
  • 14. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Operators 14 create fromEvent range … Creation map scan switchMap … Transformation debounce filter take … Filtering concat merge startWith … Combination catch retry retryWhen Error Handling share publish multicast Multicast do / tap delay toPromise … Utility every defaultIfEmpty Conditional
  • 15. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Lettable Operators 15 <T, R>(source: Observable<T>) => Observable<R> Observable.interval(1000) .pipe( filter(x => x % 2 === 0), map(x => x * x), take(5) ) .subscribe(x => console.log(x))
  • 16. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 16
  • 17. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Combining Observables: merge 17 const spring$ = Observable.of('spring', 'spring-boot', ‘spring-data'); const cloud$ = Observable.of('cloud-native', 'cloudfoundry', 'bosh'); Observable.merge(spring$, cloud$).subscribe(console.log);
  • 18. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 1818 Spring Spring spring$ cloud$ Spring Boot Spring Boot Cloud Native Cloud Native Spring Data Spring Data Cloud Foundry Cloud Foundry Bosh Bosh merge(spring$, cloud$)
  • 19. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ switchMap 19 Observable.of(1, 2, 3) .pipe( switchMap(num => Observable.of(num, num * num)) ).subscribe(console.log); 1 switchMap(num => Observable.of(num, num * num) 1 1 2 2 4 3 3 9
  • 20. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ forkJoin 20 1 const users$ = Observable.forkJoin( findUser(1), findUser(2), findUser(3) ); ... users$.subscribe(console.log); 2 3 fork join
  • 21. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ fork forkJoin 21 1 const users$ = Observable.forkJoin( findUser(1), findUser(2), findUser(3) ); users$.subscribe(console.log); 2 3 join
  • 22. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ join forkJoin 22 1 const users$ = Observable.forkJoin( findUser(1), findUser(2), findUser(3) ); users$.subscribe(console.log); fork 1 2 3 2 3
  • 23. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ join forkJoin 23 1 const users$ = Observable.forkJoin( findUser(1), findUser(2), findUser(3) ); users$.subscribe(console.log); fork 2 3[ ], ,
  • 24. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Errors 24 • When an error occurs the observable is cancelled and no data passes though • Errors are propagated to the downstream observers Observable.range(1, 20) .pipe( map(num => { if (num === 13) { throw new Error('I don't like 13'); } return num; }) )
  • 25. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Remember the Observer? 25 export interface Observer<T> { closed?: boolean; next: (value: T) => void; error: (err: any) => void; complete: () => void; }
  • 26. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Errors 26 • When an error occurs the observable is cancelled and no data passes though • Errors are propagated to the downstream observers Observable.range(1, 20) .pipe( map(num => { if (num === 13) { throw new Error('I don't like 13'); } return num; }) ).subscribe( num => console.log('Got num ' + num), err => console.log('Upssss...' + err)); map 1 1 13 X … …
  • 27. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ catchError 27 Observable.range(1, 20) .pipe( map(num => { if (num === 13) { throw new Error('I don't like 13'); } return num; }), catchError(err => Observable.range(100, 3)) ) .subscribe(console.log); Output: 1 2 3 4 5 6 7 8 9 10 11 12 100 111 112
  • 28. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Angular 28 RxJS can be used with any framework Angular has reactivity at its core, leveraging RxJS - HttpClient - Reactive Forms - Router - Component communication
  • 29. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Unsubscribing 29 @Component({ selector: 'app-mouse-position', template: '<span>{{mousePosition}}</span>' }) export class MousePositionComponent implements OnInit, OnDestroy { ngOnInit() { } ngOnDestroy() { } }
  • 30. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Unsubscribing 30 @Component({ selector: 'app-mouse-position', template: '<span>{{mousePosition}}</span>' }) export class MousePositionComponent implements OnInit, OnDestroy { ngOnInit() { } ngOnDestroy() { } } const mouseDown$ = Observable.fromEvent(document, 'mousemove') .pipe( map(val => `${val.offsetX} ${val.offsetY}`) ); Define Observable
  • 31. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Unsubscribing 31 @Component({ selector: 'app-mouse-position', template: '<span>{{mousePosition}}</span>' }) export class MousePositionComponent implements OnInit, OnDestroy { mousePosition: String; mouseSubscription: Subscription; ngOnInit() { } ngOnDestroy() { } } this.mouseSubscription = mouseDown$ .subscribe((pos: String) => this.mousePosition = pos); const mouseDown$ = Observable.fromEvent(document, 'mousemove') .pipe( map(val => `${val.offsetX} ${val.offsetY}`) ); Subscribe
  • 32. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Unsubscribing 32 @Component({ selector: 'app-mouse-position', template: '<span>{{mousePosition}}</span>' }) export class MousePositionComponent implements OnInit, OnDestroy { mousePosition: String; mouseSubscription: Subscription; ngOnInit() { } ngOnDestroy() { } } this.mouseSubscription = mouseDown$ .subscribe((pos: String) => this.mousePosition = pos); const mouseDown$ = Observable.fromEvent(document, 'mousemove') .pipe( map(val => `${val.offsetX} ${val.offsetY}`) ); this.mouseSubscription.unsubscribe();Unsubscribe
  • 33. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Async pipe 33 @Component({ selector: 'app-mouse-position', template: '<span>{{mousePosition$ | async}}</span>' }) export class MousePositionComponent implements OnInit { mousePosition$: Observable<string>; ngOnInit() { this.mousePosition$ = fromEvent(document, 'mousemove') .pipe( map(val => `${val.offsetX} ${val.offsetY}`) ); } } No subscription management
  • 34. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ HttpClient 34 - Simple API - Strong typing of request and response objects - Support for interceptors
  • 35. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ HttpClient 35 get<T>(url: string, options?: { headers?: HttpHeaders | { [header: string]: string | string[]; }; observe?: 'body'; params?: HttpParams | { [param: string]: string | string[]; }; reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; }): Observable<T>; httpClient.get<User>('http://localhost:8080/user/1') .subscribe((user: User) => console.log('User: ' + user.name));
  • 36. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Retry 36 - Retry the failed stream - Propagates the error downstream if not successful httpClient.get<User>('http://localhost:8080/user/1') .pipe( retry(3) ) httpClient.get<User>('http://localhost:8080/user/1') .pipe( retryWhen(errors => errors.pipe(delay(1000).take(3))) )
  • 37. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Reactive Forms 37 • Two options to build forms • Reactive and template-driven forms • Monitor changes by subscribing to one of the form control properties  this.favoriteConference.valueChanges this.favoriteConference.statusChanges (valid / invalid)<input formControllName=“favoriteConference” ..>
  • 38. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Server Sent Events 38 Wrapping an EventSource in an Observable const eventSource$ = Observable.create(observer => { const source = new EventSource('http://localhost:8080/search-push'); source.addEventListener('message', event => observer.next(event)); } ); * EventSource added in typings.d.ts
  • 39. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ WebSocket 39 Wrapping a WebSocket in an Observable const ws$ = Observable.create(observer => { const source = new WebSocket(‘ws://localhost:8080/search-push'); source.addEventListener('message', event => observer.next(event)); } );
  • 40. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ WebSocket 40 Wrapping a WebSocket in an Observable ws$.subscribe(...) new WebSocket(...) ws$.subscribe(...) new WebSocket(...) ws$.subscribe(...) new WebSocket(...)
  • 41. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Subscription sharing 41 const ws$ = Observable.create(observer => { const source = new WebSocket(‘ws://localhost:8080/search-push'); source.addEventListener('message', event => observer.next(event)); } ) .share();
  • 44. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 44