Angular Declarative Approach
AngularRxJS
A declarative programming paradigm concerned with data streams
and the propagation of change
. Code is reactive
when an input change leads to an automatic change in output.
Reactive Development
- React to user actions
- React to state changes
- Combine data streams
- Be resilient to failure
- Manage state
- Communicate between components
Going Reactive:
- Working with Observables
- Leverage RxJS directly operators
- Improve performance
- Simplify code, easy to read and understand
Think RxJS like a conveyor.
- Conveyor Start (Emits items) --
subscribe
- Item passes through a set of operations --
pipe
- As an observer. Next item, process it --
next()
; Error occurred, handle it --error()
; Complete, you're done --complete()
- Stop --
unsubscribe
ChangeDetectionStrategy.OnPush
Improves performance by minimizing change detection cycles.
Component is only checked when:
@Input
properties change- Event emits
- A bound Observable emits
Procedural Example
export class HomeComponent {
// this feels like a declarative, but we have to look at all the places that itemsLeftInStock to understand how the logic works.
itemsLeftInStock = this.itemService.getItemsLeftInStock();
buyItem() {
this.itemsLeftInStock = this.itemsLeftInStock - 1;
}
}
Declarative Approach
- Leverage the RxJS Observable and operators' power
- Combine data streams
- React to user actions
Declarative vs Procedural approach
Procedural Approach: Pass Parameters
// product.service.ts
getProducts(page: number) {
return this.http.get<Product[]>('/api/products', {params: {page}});
}
// component
this.productService
.getProducts(1)
.subscribe({next: (products) => (this.products = products), error: (err) => (this.errorMessage = err)});
Declarative Approach: React to Actions ❤️
// product.service.ts
products$ = this.requestedPage$.pipe(switchMap((page) => this.http.get<Product[]>('/api/products', {params: {page}})));
// component
products$ = this.productService.products$.pipe(
catchError((err) => {
this.errorMessage = err;
return EMPTY;
}),
);
operators
Combination operator
- combine to single:
merge
,concat
- flatten higher-order Observable:
mergeAll
- emit combined value:
combineLatest
,forkJoin
,withLatestFrom
Caveats
-
Don't know
this.variable
too much in angular component function, because it's hard to trace where the variable get changed. You need lots of context to understand what's going on. Unit Test is also harder.subscribe
to variables and assign variables inside the subscribe next function is like this approach.