Professional Documents
Culture Documents
ngConf 2019_ Data Composition
ngConf 2019_ Data Composition
with RxJS
(Links to slides and code provided)
Deborah Kurata
Developer | Pluralsight Author | Consultant | MVP | GDE
deborahkurata
We’ll merge
the streams!
Screenshot of a scene from the movie “GhostBusters” Burbank, CA: RCA/Columbia Pictures Home Video, 1984.
Declarative approach to
● Collecting
● Composing
● Caching
using RxJS streams
with NO subscriptions
Sample Application -> Reactive Development
Collecting
Current Pattern for Retrieving Data
@Injectable({ providedIn: 'root' })
export class ProductService {
private productsUrl = 'api/products';
getProducts(): Observable<Product[]> {
return this.http.get<Product[]>(this.productsUrl)
.pipe(
tap(console.log),
catchError(this.handleError)
);
}
}
Declarative Pattern for Retrieving Data
@Injectable({ providedIn: 'root' })
export class ProductService {
private productsUrl = 'api/products';
products$ = this.http.get<Product[]>(this.productsUrl)
.pipe(
tap(console.log),
catchError(this.handleError)
);
products$ = this.productService.products$
.pipe(
catchError(error => {
this.errorMessage = error;
return of(null);
}));
productCategories$ = this.http.get<ProductCategory[]>
(this.productCategoriesUrl)
.pipe(
tap(console.log),
catchError(this.handleError)
);
products$ = this.productService.productsWithCategory$
.pipe(
catchError(error => {
this.errorMessage = error;
return of(null);
}));
Emit a value
Create an action Combine action
every time an
stream and data streams
action occurs
Creating an Action Stream
private productSelectedAction = new Subject<number>();
productSelectedAction$ = this.productSelectedAction.asObservable();
1 3 14
combineLatest(data$, action$)
1 14
combineLatest(data$, action$)
[ [
[{saw}, [{saw},
{rake}, {rake},
{axe}], {axe}],
1] 14]
Caching
Cache the Array?
@Injectable({ providedIn: 'root' })
export class ProductService {
private productsUrl = 'api/products';
products: Product[];
products$ = this.http.get<Product[]>(this.productsUrl)
.pipe(
map(data => this.products = data),
catchError(this.handleError)
);
productSuppliers$ = this.productService.selectedProductSuppliers$
.pipe(
catchError(error => {
this.errorMessage = error;
return of(null);
}));
We’ll merge
the streams!
Screenshot of a scene from the movie “GhostBusters” Burbank, CA: RCA/Columbia Pictures Home Video, 1984.
Component
vm$ = combineLatest(
[this.product$,
this.productSuppliers$,
this.pageTitle$])
Array
.pipe(
destructuring
filter(([product]) => !!product),
map(([product, productSuppliers, pageTitle]) =>
({ product, productSuppliers, pageTitle }))
);
*Thanks to Sander Elias for showing me this technique
Template
<div *ngIf="vm$ | async as vm">
<div>{{vm.pageTitle}}</div>
...
<div>Name:</div>
<div>{{vm.product.productName}}</div>
...
<tr *ngFor="let supplier of vm.productSuppliers">
...
Declarative, Reactive Streams
CONS PROS
● Picking the right operator is not ● Composable streams
always easy ● Leverages power of RxJS
● Difficult to debug Observables operators
● Sharing Observables is easy
(cache)
● Effectively react to actions
● OnPush for improved
performance
Data Composition with RxJS
Slides:
http://bit.ly/deborahk-ngconf2019
Code:
https://github.com/DeborahK/Angular-DD
Twitter:
deborahkurata