SlideShare a Scribd company logo
June 15, 2017
IPT – Intellectual
Products & Technologies
NGRX Apps in
Depth – RxJS,
Reselect, Router,
IndexedDB,
@Effects
Trayan Iliev
tiliev@iproduct.org
http://iproduct.org
Copyright © 2003-2017 IPT - Intellectual
Products & Technologies
IPT - Intellectual Products & Technologies
2
Since 2003 we provide trainings and share skills in
JS/ TypeScript/ Node/ Express/ Socket.IO/ NoSQL/
Angular/ React / Java SE/ EE/ Web/ REST SOA:
 Node.js + Express/ hapi + React.js + Redux + GraphQL
 Angular + TypeScript + Redux (ngrx)
 Java EE6/7, Spring, JSF, Portals: Liferay, GateIn
 Reactive IoT with Reactor / RxJava / RxJS
 SOA & Distributed Hypermedia APIs (REST)
 Domain Driven Design & Reactive Microservices
3
NGRX Apps in Depth
 State management, event sourcing, DDD, reactive
programming, and stream based service architectures
 Flux, Redux & NGRX: Reactive Extensions for Angular
 Composing NGRX Reducers, Selectors & Middleware
 Computing derived data (memoization): Reselect, RxJS
 Observable (hot) streams of async actions – isolating
side effects using @Effect & RxJS reactive transforms
 NGRX-Router integration, Material Design, PrimeNG
 Normalization/denormalization, local data – IndexedDB
 Example app – code structure, lazy loading, etc.
Where to Find the Demo Code?
4
Angular and NGRX demos are available @GitHub:
https://github.com/iproduct/course-angular
 ipt-knowledge-manager – NGRX, Reselect, RxJS
@Effects, modules lazy loading, AOT
 angular2-change-detection-demos – modified from
https://github.com/thoughtram/angular2-change-
detection-demos
 ngrx-example-app – NGRX official demo from
https://github.com/ngrx/example-app, IndexedDB
Data / Event / Message Streams
5
“Conceptually, a stream is a (potentially never-ending)
flow of data records, and a transformation is an
operation that takes one or more streams as input,
and produces one or more output streams as a
result.”
Apache Flink: Dataflow Programming Model
Data Stream Programming
6
The idea of abstracting logic from execution is hardly
new -- it was the dream of SOA. And the recent
emergence of microservices and containers shows that
the dream still lives on.
For developers, the question is whether they want to
learn yet one more layer of abstraction to their coding.
… there's the elusive promise of a common API to
streaming engines that in theory should let you mix and
match, or swap in and swap out.
Tony Baer (Ovum) @ ZDNet - Apache Beam and Spark:
New comopetition for squashing the Lambda Architecture?
Listen to Quark:
7
“Good things come in small packages”
Quark – Star Trek DS9 character
https://en.wikipedia.org/w/index.php?curid=12544179, Star Trek: Deep Space Nine, "Emissary", Fair use
Lambda Architecture - I
8
https://commons.wikimedia.org/w/index.php?curid=34963986, By Textractor - Own work, CC BY-SA 4
Lambda Architecture - II
9
https://commons.wikimedia.org/w/index.php?curid=34963987, By Textractor - Own work, CC BY-SA 4
Lambda Architecture - III
10
 Data-processing architecture designed to handle
massive quantities of data by using both batch- and
stream-processing methods
 Balances latency, throughput, fault-tolerance, big data,
real-time analytics, mitigates the latencies of map-
reduce
 Data model with an append-only, immutable data
source that serves as a system of record
 Ingesting and processing timestamped events that are
appended to existing events. State is determined from
the natural time-based ordering of the data.
Druid Distributed Data Store
11
https://commons.wikimedia.org/w/index.php?curid=33899448 By Fangjin Yang - sent to me personally, GFDL
Apache
ZooKeeper
MySQL /
PostgreSQL
HDFS /
Amazon S3
Lambda Architecture: Projects - I
12
Direct Acyclic Graphs - DAG
13
14
 Performance is about 2 things:
– Throughput – units per second, and
– Latency – response time, responsiveness - especially
important from end user perspective (front-end)
 Real-time – time constraint from input to response
regardless of system load.
 Hard real-time system if this constraint is not honored then
a total system failure can occur.
 Soft real-time system – low latency response with little
deviation in response time
 100 nano-seconds to 100 milli-seconds. [Peter Lawrey]
What High Performance Means?
Synchronous vs. Asynchronous IO
15
DB
Synchronous
A
A
B
B
DB
Asynchronous
A
B
C
D
A
B
C
D
Tracking Complexity
16
We need tools to cope with all that complexity inherent in
real world applications.
Simple solutions are needed – cope with problems through
divide and concur on different levels of abstraction:
Domain Driven Design (DDD) – back to basics:
domain objects, data and logic.
Described by Eric Evans in his book:
Domain Driven Design: Tackling Complexity in the Heart of
Software, 2004
Microservices and DDD
17
Main concepts:
 Entities, value objects and modules
 Aggregates and Aggregate Roots:
value < entity < aggregate < module < BC
 Aggregate Roots are exposed as Open Host Services
 Hexagonal architecture :
OUTSIDE <-> transformer <->
( application <-> domain )
Imperative and Reactive
18
We live in a Connected Universe
... there is hypothesis that all
the things in the Universe are
intimately connected, and you
can not change a bit without
changing all.
Action – Reaction principle is
the essence of how Universe
behaves.
Imperative and Reactive
 Reactive Programming: using static or dynamic data
flows and propagation of change
Example: a := b + c
 Functional Programming: evaluation of mathematical
functions,
➢ Avoids changing-state and mutable data, declarative
programming
➢ Side effects free => much easier to understand and
predict the program behavior.
Example: Observable.from(['Reactive', 'Extensions','JS'])
.take(2).map(s => `${s}: on ${new Date()}`)
.subscribe(s => console.log(s));
Functional Reactive (FRP)
20
According to Connal Elliot's (ground-breaking paper
@Conference on Functional Programming, 1997), FRP is:
(a) Denotative (Compositional): Observables can be
composed with higher-order combinators
(b) Temporally continuous (Lazy): Observables do
not start emitting data until an Observer has
subscribed
Reactive Manifesto
21
[http://www.reactivemanifesto.org]
22
 Message Driven – asynchronous message-passing
allows to establish a boundary between components
that ensures loose coupling, isolation, location
transparency, and provides the means to delegate
errors as messages.
[Reactive Manifesto]
Scalable, Massively Concurrent
Reactive Programming Specs
23
 Reactive Streams Specification
[http://www.reactive-streams.org/]
 ES7 Observable Spec (implemented by RxJS 5)
[https://github.com/tc39/proposal-observable]
Open source polyglot project ReactiveX (Reactive
Extensions) [http://reactivex.io]:
Rx = Observables + LINQ + Schedulers :)
Java: RxJava, JavaScript: RxJS, C#: Rx.NET, Scala: RxScala,
Clojure: RxClojure, C++: RxCpp, Ruby: Rx.rb, Python: RxPY,
Groovy: RxGroovy, JRuby: RxJRuby, Kotlin: RxKotlin ...
Reactive Streams Spec.
24
 Publisher – provider of potentially unbounded number
of sequenced elements, according to Subscriber(s)
demand.
Publisher.subscribe(Subscriber) => onSubscribe onNext*
(onError | onComplete)?
 Subscriber – calls Subscription.request(long) to
receive notifications
 Subscription – one-to-one Subscriber ↔ Publisher,
request data and cancel demand (allow cleanup).
 Processor = Subscriber + Publisher
ES7 Observable Spec (RxJS 5)
25
interface Observable {
constructor(subscriber : SubscriberFunction);
subscribe(observer : Observer) : Subscription;
subscribe(onNext : Function,
onError? : Function,
onComplete? : Function) : Subscription;
[Symbol.observable]() : Observable;
static of(...items) : Observable;
static from(iterableOrObservable) : Observable;
}
interface Subscription {
unsubscribe() : void;
get closed() : Boolean;
}
26
RxJS – JS ReactiveX (Reactive Extensions)
[http://reactivex.io, https://github.com/ReactiveX]
 ReactiveX is a polyglot library for composing asynchronous
event streams (observable sequences).
 It extends the observer pattern by declarative composition of
functional transformations on events streams (e.g. map-filter-
reduce, etc.)
 Abstracs away low-level concerns like concurrency,
synchronization, and non-blocking I/O.
 Follows the next - error - completed event flow
 Allows natural implementation of Redux design pattern
 Alternative (together with promises) for solving “callback hell”
problem
27
RxJS Resources
RxMarbles:
http://rxmarbles.com/
RxJS Coans:
https://github.com/Reactive-Extensions/RxJSKoans
Learn RxJS:
https://www.learnrxjs.io/
Source: https://github.com/ReactiveX/rxjs/blob/master/doc/asset/marble-diagram-anatomy.svg, Apache v2
Anatomy of Rx Operator
Example: combineLatest()
29
https://projectreactor.io/core/docs/api/, Apache Software License 2.0
Example: switchMap()
30
http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html, Apache Software License 2.0
Hot and Cold Event Streams
31
 PULL-based (Cold Event Streams) – Cold streams are
streams that run their sequence when and if they are
subscribed to. They present the sequence from the start
to each subscriber.
 PUSH-based (Hot Event Streams) – Hot streams emit
values independent of individual subscriptions. They
have their own timeline and events occur whether
someone is listening or not. An example of this is
mouse events. A mouse is generating events regardless
of whether there is a subscription. When subscription is
made observer receives current events as they happen.
Converting Cold to Hot Stream
32
Flux Design Pattern
Source: Flux in GitHub, https://github.com/facebook/flux, License: BSD 3-clause "New" License
Linear flow:
Source: @ngrx/store in GitHub, https://gist.github.com/btroncone/a6e4347326749f938510
Redux Design Pattern
Source: RxJava 2 API documentation, http://reactivex.io/RxJava/2.x/javadoc/
Redux == Rx Scan Opearator
Source: RxJS docs, https://github.com/ReactiveX/rxjs/blob/master/doc/tutorial/applications.md
Redux in Plain RxJS
import Immutable from 'immutable';
import someObservable from './someObservable';
import someOtherObservable from './someOtherObservable';
var initialState = { foo: 'bar' };
var state = Observable.merge(
someObservable,
someOtherObservable
).scan((state, changeFn) => changeFn(state),
Immutable.fromJS(initialState));
export default state;
Source: RxJS docs, https://github.com/ReactiveX/rxjs/blob/master/doc/tutorial/applications.md
Redux in Plain RxJS
state.js:
import Immutable from 'immutable';
import someObservable from './someObservable';
import someOtherObservable from './someOtherObservable';
var initialState = { foo: 'bar' };
var state = Observable.merge(
someObservable,
someOtherObservable
).scan((state, changeFn) => changeFn(state),
Immutable.fromJS(initialState));
export default state;
Redux in Plain RxJS
client.js:
import state from './state';
state.subscribe(state => {
document.querySelector('#text').innerHTML =
state.get('foo');
});
Source: RxJS docs, https://github.com/ReactiveX/rxjs/blob/master/doc/tutorial/applications.md
NGRX: Reactive Extensions for Angular
 core – core functionality for the ngrx platform
 store – RxJS powered state management for Angular
applications, inspired by Redux
 router-store – bindings to connect the Angular Router to
@ngrx/store
 effects – side effect model for @ngrx/store
 db – RxJS powered IndexedDB for Angular apps
 notify – Web Notifications powered by RxJS for Angular
 store-devtools, store-log-monitor - dev tools, monitoring
 example-app – example app showcasing ngrx platform
Bootstraping NGRX App
 In app.module.ts:
@NgModule({
imports: [
StoreModule.provideStore(reducer),
RouterStoreModule.connectRouter(),
StoreDevtoolsModule.instrumentOnlyWithExtension(),
EffectsModule.run(BookEffects),
EffectsModule.run(CollectionEffects),
DBModule.provideDB(schema),
...
]
...
NGRX: Defining State & Reducers
 in root.reducer.ts:
export interface RootState {
router: fromRouter.RouterState;
ui: fromUi.State;
users: fromUsers.State;
tests: fromTests.State;
}
export const reducers: ReducersMap = {
router: fromRouter.routerReducer,
ui: fromUi.reducer,
users: fromUsers.reducer,
tests: fromTests.reducer
};
NGRX: Composing Root Reducer
 in root.reducer.ts:
const developmentReducer: ActionReducer<S> =
compose(storeFreeze, combineReducers)(reducers);
const productionReducer: ActionReducer<S> =
combineReducers(reducers);
export function rootReducer(state: any, action: any) {
if (environment.production) {
return productionReducer(state, action)
} else {
return developmentReducer(state,action)
}
}
Store Middleware Composition
Needs to be statically importable by AOT
NGRX Selectors
 A selector function is a factory for mapping functions.
 Returned function maps from larger state tree into a feature
substate tree (destructing the larger state).
 Selectors are used with the `select` ngrx Store operator.
Following example shows selector selecting the `users`
sub-state:
class ClientComponent {
constructor(store$: Observable<State>) {
this.usersState$ = store$.select(getUsersState);
}
}
Composing User Selectors
 in users/user.selectors.ts:
// User state selectors
export const getEntities =
(state: State) => state.entities;
export const getIds = (state: State) => state.ids;
export const getAll =
createSelector(getEntities, getIds, (entities, ids)=>{
return ids.map(id => entities[id]);
});
// Root state selectors
export const getUsersState =
(state: RootState) => state.users;
export const getUsers =
createSelector(getUsersState, getAll);
Using Reselect
 in users/user.selectors.ts:
// User state selectors
export const getEntities =
(state: State) => state.entities;
export const getIds = (state: State) => state.ids;
export const getAll =
createSelector(getEntities, getIds, (entities, ids)=>{
return ids.map(id => entities[id]);
});
// Root state selectors
export const getUsersState =
(state: RootState) => state.users;
export const getUsers =
createSelector(getUsersState, getAll);
Computing Derived Data: Reselect
 Selectors can compute derived data, allowing Redux to
store the minimal possible state.
 Selectors are efficient. A selector is not recomputed
unless one of its arguments change.
 Selectors are composable. They can be used as input
to other selectors.
 Works correctly only when combined with immutability.
Computing Derived Data: Reselect
import { createSelector } from 'reselect'
const getVisibilityFilter =
(state) => state.visibilityFilter
const getTodos = (state) => state.todos
export const getVisibleTodos = createSelector(
[ getVisibilityFilter, getTodos ],
(visibilityFilter, todos) => {
switch (visibilityFilter) {
case 'SHOW_ALL':
return todos
case 'SHOW_COMPLETED':
return todos.filter(t => t.completed)
case 'SHOW_ACTIVE':
return todos.filter(t => !t.completed)
}});
Can You Spot the Problem Here?
const isFirstTodoCompleteSelector = createSelector(
state => state.todos[0], todo => todo && todo.completed)
export default function todos(state = initState, action)
{
switch (action.type) {
case COMPLETE_ALL:
const allMarked = state.every(todo => todo.completed)
return state.map(todo => {
todo.completed = !allMarked
return todo
})
default: return state
}}
Can We Memoize without Reselect?
 In users/components/user-list.component.ts:
public ngOnInit() {
this.store.dispatch(this.userActions.loadUsers());
this.subscription = this.selectedId$
.filter(id => !!id)
.distinctUntilChanged()
.subscribe(id => this.store.dispatch(
go(['users', id])));
Router Integration, MD, PrimeNG
State Normalization / Denormalization
[http://redux.js.org/docs/recipes/reducers/NormalizingStateShape.html]
 When a piece of data is duplicated in several places, it
becomes harder to make sure that it is updated
appropriately
 Nested data means that the corresponding reducer
logic has to be more nested or more complex. In
particular, trying to update a deeply nested field can
become very ugly very fast.
 Since immutable data updates require all ancestors in
the state tree to be copied and updated as well, an
update to a deeply nested data object could force
totally unrelated UI components to re-render even if the
data they're displaying hasn't actually changed.
Example: Users State Normalization
export interface State {
ids: IdentityType[];
entities: { [id: string]: User };
selectedUserId: IdentityType | null;
loading: boolean;
};
export const initialState: State = {
ids: [],
entities: {},
selectedUserId: null,
loading: false
};
export function usersReducer(state = initialState,
action: Action): State {
switch (action.type) { ...
IndexedDB
 IndexedDB is a low-level API for client-side storage of
significant amounts of structured data (key-value pairs),
including files/blobs.
 API uses indexes to enable high-performance searches
of this data. Web Storage - useful for smaller data.
 IndexedDB is built on a transactional database model –
everything you do in IndexedDB always happens in the
context of a transaction.
 The IndexedDB API is mostly asynchronous – you have
to pass a callback function.
 IndexedDB uses DOM events to notify you when
results are available - type prop ("success" or "error").
Example: @Effect and IndexedDB
constructor(private actions$: Actions, private db:
Database) { }
@Effect({ dispatch: false })
openDB$: Observable<any> = defer(() => {
return this.db.open('books_app');
});
@Effect()
loadCollection$: Observable<Action> = this.actions$
.ofType(collection.LOAD)
.startWith(new collection.LoadAction())
.switchMap(() => this.db.query('books').toArray()
.map((books: Book[]) =>
new collection.LoadSuccessAction(books))
.catch(error => of(
new collection.LoadFailAction(error))) );
@Effect()
addBookToCollection$: Observable<Action> =
this.actions$
.ofType(collection.ADD_BOOK)
.map((action: collection.AddBookAction) =>
action.payload)
.mergeMap(book =>
this.db.insert('books', [ book ])
.map(() =>
new collection.AddBookSuccessAction(book))
.catch(() => of(
new collection.AddBookFailAction(book)))
);
Example: @Effect and IndexedDB
@Effect()
removeBookFromCollection$: Observable<Action> =
this.actions$
.ofType(collection.REMOVE_BOOK)
.map((action: collection.RemoveBookAction) =>
action.payload)
.mergeMap(book =>
this.db.executeWrite('books', 'delete', [book.id])
.map(() =>
new collection.RemoveBookSuccessAction(book))
.catch(() => of(
new collection.RemoveBookFailAction(book)))
);
Example: @Effect and IndexedDB
export interface RootState {
ui: fromUi.State;
router: fromRouter.RouterState;
}
export interface ReducersMap {
[key: string]: ActionReducer<any>; }
const reducers: ReducersMap = {
ui: fromUi.reducer,
router: fromRouter.routerReducer
};
const devProdReducers: ReducersMap = {
developmentReducer:
compose(storeFreeze, combineReducers)(reducers),
productionReducer: combineReducers(reducers)
}
How to Lazy Load Reducers? - I
export function addReducer<S>(name: string, reducer:
ActionReducer<S>): void {
reducers[name] = reducer;
devProdReducers['developmentReducer'] =
compose(storeFreeze, combineReducers)(reducers);
devProdReducers['productionReducer'] =
combineReducers(reducers);
}
export function rootReducer(state: any, action: any) {
if (environment.production) {
return devProdReducers.productionReducer(state, action)
} else {
return devProdReducers.developmentReducer(state,action)
}
}
How to Lazy Load Reducers? - II
This works happily with AOT!
 in lazy loaded module (users/user.module.ts):
@NgModule({ ... })
export class UserModule {
constructor() {
addReducer<UserState>('users', usersReducer);
}
}
export interface RootState extends OldRootState {
users: UserState;
}
 Then everywhere in lazy loaded module import augmented
RootState from that lazy loaded module (from
users/user.module.ts, not from root.reducer.ts).
Adding New Lazy Loaded Reducer
Where to Find the Demo Code?
60
Angular and NGRX demos are available @GitHub:
https://github.com/iproduct/course-angular
 ipt-knowledge-manager – NGRX, Reselect, RxJS
@Effects, modules lazy loading, AOT
 angular2-change-detection-demos – modified from
https://github.com/thoughtram/angular2-change-
detection-demos
 ngrx-example-app – NGRX official demo from
https://github.com/ngrx/example-app, IndexedDB
Thank’s for Your Attention!
61
Trayan Iliev
CEO of IPT – Intellectual Products
& Technologies
http://iproduct.org/
http://robolearn.org/
https://github.com/iproduct
https://twitter.com/trayaniliev
https://www.facebook.com/IPT.EACAD
https://plus.google.com/+IproductOrg

More Related Content

PDF
Stream Processing with CompletableFuture and Flow in Java 9
PDF
Rapid Web API development with Kotlin and Ktor
PDF
IPT Reactive Java IoT Demo - BGOUG 2018
PDF
Reactive Microservices with Spring 5: WebFlux
PDF
Spring 5 Webflux - Advances in Java 2018
PDF
Microservices with Spring 5 Webflux - jProfessionals
PDF
What's new in java 9?
PDF
Making Machine Learning Easy with H2O and WebFlux
Stream Processing with CompletableFuture and Flow in Java 9
Rapid Web API development with Kotlin and Ktor
IPT Reactive Java IoT Demo - BGOUG 2018
Reactive Microservices with Spring 5: WebFlux
Spring 5 Webflux - Advances in Java 2018
Microservices with Spring 5 Webflux - jProfessionals
What's new in java 9?
Making Machine Learning Easy with H2O and WebFlux

What's hot (20)

PDF
Predictable reactive state management - ngrx
PDF
Angular Offline Progressive Web Apps With NodeJS
PDF
Reflective injection using TypeScript
PDF
Hybrid Cloud, Kubeflow and Tensorflow Extended [TFX]
PPTX
Enterprise Software Architecture styles
PDF
Introduction to the Processor API
PDF
Introducing Arc: A Common Intermediate Language for Unified Batch and Stream...
PDF
Reactive Java Robotics IoT - jPrime 2016
PDF
IPT High Performance Reactive Java BGOUG 2016
PDF
Reactive Java Robotics and IoT - IPT Presentation @ Voxxed Days 2016
PPTX
Flink Forward SF 2017: Erik de Nooij - StreamING models, how ING adds models ...
PPT
Zou Layered VO PDCAT2008 V0.5 Concise
PPTX
Linq
KEY
Introducing LINQ
PDF
Predictable reactive state management for enterprise apps using NGRX/platform
PDF
Iot Toolkit and the Smart Object API - Architecture for Interoperability
PDF
State management for enterprise angular applications
PPT
Introduction Of Linq , ASP.NET Training Ahmedabad, ASP.NET Course Ahmedabad
PDF
Advanced Model Inferencing leveraging Kubeflow Serving, KNative and Istio
Predictable reactive state management - ngrx
Angular Offline Progressive Web Apps With NodeJS
Reflective injection using TypeScript
Hybrid Cloud, Kubeflow and Tensorflow Extended [TFX]
Enterprise Software Architecture styles
Introduction to the Processor API
Introducing Arc: A Common Intermediate Language for Unified Batch and Stream...
Reactive Java Robotics IoT - jPrime 2016
IPT High Performance Reactive Java BGOUG 2016
Reactive Java Robotics and IoT - IPT Presentation @ Voxxed Days 2016
Flink Forward SF 2017: Erik de Nooij - StreamING models, how ING adds models ...
Zou Layered VO PDCAT2008 V0.5 Concise
Linq
Introducing LINQ
Predictable reactive state management for enterprise apps using NGRX/platform
Iot Toolkit and the Smart Object API - Architecture for Interoperability
State management for enterprise angular applications
Introduction Of Linq , ASP.NET Training Ahmedabad, ASP.NET Course Ahmedabad
Advanced Model Inferencing leveraging Kubeflow Serving, KNative and Istio
Ad

Similar to NGRX Apps in Depth (20)

PDF
Reactive robotics io_t_2017
PDF
Reactive Java Robotics and IoT 2016
PDF
Java & JavaScipt Reactive Robotics and IoT 2016 @ jProfessionals
PDF
Reactive Java Robotics & IoT with Spring Reactor
PDF
From User Action to Framework Reaction
PDF
From User Action to Framework Reaction
PPTX
Cytoscape CI Chapter 2
PDF
Exploring MERN Stack and Tech Stacks: A Comparative Analysis
PPT
Reactive java programming for the impatient
PPTX
Madeo - a CAD Tool for reconfigurable Hardware
PDF
Elastic r sc10-tutorial
PDF
exploring-spring-boot-clients.pdf Spring Boot
PDF
DZone_RC_RxJS
PPTX
IT TRENDS AND PERSPECTIVES 2016
PDF
Genomic Computation at Scale with Serverless, StackStorm and Docker Swarm
PDF
UniK - a unikernel compiler and runtime
PDF
Reactive in Android and Beyond Rx
PPTX
Microservices Part 4: Functional Reactive Programming
PDF
Cyclone DDS Unleashed: ROS & Cyclone DDS.pdf
PDF
Breaking a monolith: In-place refactoring with service-oriented architecture ...
Reactive robotics io_t_2017
Reactive Java Robotics and IoT 2016
Java & JavaScipt Reactive Robotics and IoT 2016 @ jProfessionals
Reactive Java Robotics & IoT with Spring Reactor
From User Action to Framework Reaction
From User Action to Framework Reaction
Cytoscape CI Chapter 2
Exploring MERN Stack and Tech Stacks: A Comparative Analysis
Reactive java programming for the impatient
Madeo - a CAD Tool for reconfigurable Hardware
Elastic r sc10-tutorial
exploring-spring-boot-clients.pdf Spring Boot
DZone_RC_RxJS
IT TRENDS AND PERSPECTIVES 2016
Genomic Computation at Scale with Serverless, StackStorm and Docker Swarm
UniK - a unikernel compiler and runtime
Reactive in Android and Beyond Rx
Microservices Part 4: Functional Reactive Programming
Cyclone DDS Unleashed: ROS & Cyclone DDS.pdf
Breaking a monolith: In-place refactoring with service-oriented architecture ...
Ad

More from Trayan Iliev (11)

PDF
Learning Programming Using Robots - Sofia University Conference 2018
PDF
Active Learning Using Connected Things - 2018 (in Bulgarian)
PDF
Fog Computing - DEV.BG 2018
PDF
React HOCs, Context and Observables
ODP
Hackathon: “IPTPI and LeJaRo Meet The Real World”
PDF
IPT angular2 typescript SPA 2016
PDF
New MVC 1.0 JavaEE 8 API
PDF
IPT High Performance Reactive Programming with JAVA 8 and JavaScript
PDF
IPT Workshops on Java Robotics and IoT
PDF
IPT – Java Robotics and IoT
PDF
Novelties in Java EE 7: JAX-RS 2.0 + IPT REST HATEOAS Polling Demo @ BGOUG Co...
Learning Programming Using Robots - Sofia University Conference 2018
Active Learning Using Connected Things - 2018 (in Bulgarian)
Fog Computing - DEV.BG 2018
React HOCs, Context and Observables
Hackathon: “IPTPI and LeJaRo Meet The Real World”
IPT angular2 typescript SPA 2016
New MVC 1.0 JavaEE 8 API
IPT High Performance Reactive Programming with JAVA 8 and JavaScript
IPT Workshops on Java Robotics and IoT
IPT – Java Robotics and IoT
Novelties in Java EE 7: JAX-RS 2.0 + IPT REST HATEOAS Polling Demo @ BGOUG Co...

Recently uploaded (20)

PDF
Design an Analysis of Algorithms II-SECS-1021-03
PPTX
L1 - Introduction to python Backend.pptx
PDF
System and Network Administration Chapter 2
PDF
AI in Product Development-omnex systems
PPTX
VVF-Customer-Presentation2025-Ver1.9.pptx
PDF
medical staffing services at VALiNTRY
PPTX
CHAPTER 12 - CYBER SECURITY AND FUTURE SKILLS (1) (1).pptx
PDF
2025 Textile ERP Trends: SAP, Odoo & Oracle
PDF
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
PPT
Introduction Database Management System for Course Database
PPTX
Operating system designcfffgfgggggggvggggggggg
PPT
JAVA ppt tutorial basics to learn java programming
PDF
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
PPTX
history of c programming in notes for students .pptx
PDF
Complete React Javascript Course Syllabus.pdf
PDF
How to Migrate SBCGlobal Email to Yahoo Easily
PPTX
Materi-Enum-and-Record-Data-Type (1).pptx
PDF
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
PDF
Upgrade and Innovation Strategies for SAP ERP Customers
PDF
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
Design an Analysis of Algorithms II-SECS-1021-03
L1 - Introduction to python Backend.pptx
System and Network Administration Chapter 2
AI in Product Development-omnex systems
VVF-Customer-Presentation2025-Ver1.9.pptx
medical staffing services at VALiNTRY
CHAPTER 12 - CYBER SECURITY AND FUTURE SKILLS (1) (1).pptx
2025 Textile ERP Trends: SAP, Odoo & Oracle
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
Introduction Database Management System for Course Database
Operating system designcfffgfgggggggvggggggggg
JAVA ppt tutorial basics to learn java programming
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
history of c programming in notes for students .pptx
Complete React Javascript Course Syllabus.pdf
How to Migrate SBCGlobal Email to Yahoo Easily
Materi-Enum-and-Record-Data-Type (1).pptx
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
Upgrade and Innovation Strategies for SAP ERP Customers
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free

NGRX Apps in Depth

  • 1. June 15, 2017 IPT – Intellectual Products & Technologies NGRX Apps in Depth – RxJS, Reselect, Router, IndexedDB, @Effects Trayan Iliev tiliev@iproduct.org http://iproduct.org Copyright © 2003-2017 IPT - Intellectual Products & Technologies
  • 2. IPT - Intellectual Products & Technologies 2 Since 2003 we provide trainings and share skills in JS/ TypeScript/ Node/ Express/ Socket.IO/ NoSQL/ Angular/ React / Java SE/ EE/ Web/ REST SOA:  Node.js + Express/ hapi + React.js + Redux + GraphQL  Angular + TypeScript + Redux (ngrx)  Java EE6/7, Spring, JSF, Portals: Liferay, GateIn  Reactive IoT with Reactor / RxJava / RxJS  SOA & Distributed Hypermedia APIs (REST)  Domain Driven Design & Reactive Microservices
  • 3. 3 NGRX Apps in Depth  State management, event sourcing, DDD, reactive programming, and stream based service architectures  Flux, Redux & NGRX: Reactive Extensions for Angular  Composing NGRX Reducers, Selectors & Middleware  Computing derived data (memoization): Reselect, RxJS  Observable (hot) streams of async actions – isolating side effects using @Effect & RxJS reactive transforms  NGRX-Router integration, Material Design, PrimeNG  Normalization/denormalization, local data – IndexedDB  Example app – code structure, lazy loading, etc.
  • 4. Where to Find the Demo Code? 4 Angular and NGRX demos are available @GitHub: https://github.com/iproduct/course-angular  ipt-knowledge-manager – NGRX, Reselect, RxJS @Effects, modules lazy loading, AOT  angular2-change-detection-demos – modified from https://github.com/thoughtram/angular2-change- detection-demos  ngrx-example-app – NGRX official demo from https://github.com/ngrx/example-app, IndexedDB
  • 5. Data / Event / Message Streams 5 “Conceptually, a stream is a (potentially never-ending) flow of data records, and a transformation is an operation that takes one or more streams as input, and produces one or more output streams as a result.” Apache Flink: Dataflow Programming Model
  • 6. Data Stream Programming 6 The idea of abstracting logic from execution is hardly new -- it was the dream of SOA. And the recent emergence of microservices and containers shows that the dream still lives on. For developers, the question is whether they want to learn yet one more layer of abstraction to their coding. … there's the elusive promise of a common API to streaming engines that in theory should let you mix and match, or swap in and swap out. Tony Baer (Ovum) @ ZDNet - Apache Beam and Spark: New comopetition for squashing the Lambda Architecture?
  • 7. Listen to Quark: 7 “Good things come in small packages” Quark – Star Trek DS9 character https://en.wikipedia.org/w/index.php?curid=12544179, Star Trek: Deep Space Nine, "Emissary", Fair use
  • 8. Lambda Architecture - I 8 https://commons.wikimedia.org/w/index.php?curid=34963986, By Textractor - Own work, CC BY-SA 4
  • 9. Lambda Architecture - II 9 https://commons.wikimedia.org/w/index.php?curid=34963987, By Textractor - Own work, CC BY-SA 4
  • 10. Lambda Architecture - III 10  Data-processing architecture designed to handle massive quantities of data by using both batch- and stream-processing methods  Balances latency, throughput, fault-tolerance, big data, real-time analytics, mitigates the latencies of map- reduce  Data model with an append-only, immutable data source that serves as a system of record  Ingesting and processing timestamped events that are appended to existing events. State is determined from the natural time-based ordering of the data.
  • 11. Druid Distributed Data Store 11 https://commons.wikimedia.org/w/index.php?curid=33899448 By Fangjin Yang - sent to me personally, GFDL Apache ZooKeeper MySQL / PostgreSQL HDFS / Amazon S3
  • 14. 14  Performance is about 2 things: – Throughput – units per second, and – Latency – response time, responsiveness - especially important from end user perspective (front-end)  Real-time – time constraint from input to response regardless of system load.  Hard real-time system if this constraint is not honored then a total system failure can occur.  Soft real-time system – low latency response with little deviation in response time  100 nano-seconds to 100 milli-seconds. [Peter Lawrey] What High Performance Means?
  • 15. Synchronous vs. Asynchronous IO 15 DB Synchronous A A B B DB Asynchronous A B C D A B C D
  • 16. Tracking Complexity 16 We need tools to cope with all that complexity inherent in real world applications. Simple solutions are needed – cope with problems through divide and concur on different levels of abstraction: Domain Driven Design (DDD) – back to basics: domain objects, data and logic. Described by Eric Evans in his book: Domain Driven Design: Tackling Complexity in the Heart of Software, 2004
  • 17. Microservices and DDD 17 Main concepts:  Entities, value objects and modules  Aggregates and Aggregate Roots: value < entity < aggregate < module < BC  Aggregate Roots are exposed as Open Host Services  Hexagonal architecture : OUTSIDE <-> transformer <-> ( application <-> domain )
  • 18. Imperative and Reactive 18 We live in a Connected Universe ... there is hypothesis that all the things in the Universe are intimately connected, and you can not change a bit without changing all. Action – Reaction principle is the essence of how Universe behaves.
  • 19. Imperative and Reactive  Reactive Programming: using static or dynamic data flows and propagation of change Example: a := b + c  Functional Programming: evaluation of mathematical functions, ➢ Avoids changing-state and mutable data, declarative programming ➢ Side effects free => much easier to understand and predict the program behavior. Example: Observable.from(['Reactive', 'Extensions','JS']) .take(2).map(s => `${s}: on ${new Date()}`) .subscribe(s => console.log(s));
  • 20. Functional Reactive (FRP) 20 According to Connal Elliot's (ground-breaking paper @Conference on Functional Programming, 1997), FRP is: (a) Denotative (Compositional): Observables can be composed with higher-order combinators (b) Temporally continuous (Lazy): Observables do not start emitting data until an Observer has subscribed
  • 22. 22  Message Driven – asynchronous message-passing allows to establish a boundary between components that ensures loose coupling, isolation, location transparency, and provides the means to delegate errors as messages. [Reactive Manifesto] Scalable, Massively Concurrent
  • 23. Reactive Programming Specs 23  Reactive Streams Specification [http://www.reactive-streams.org/]  ES7 Observable Spec (implemented by RxJS 5) [https://github.com/tc39/proposal-observable] Open source polyglot project ReactiveX (Reactive Extensions) [http://reactivex.io]: Rx = Observables + LINQ + Schedulers :) Java: RxJava, JavaScript: RxJS, C#: Rx.NET, Scala: RxScala, Clojure: RxClojure, C++: RxCpp, Ruby: Rx.rb, Python: RxPY, Groovy: RxGroovy, JRuby: RxJRuby, Kotlin: RxKotlin ...
  • 24. Reactive Streams Spec. 24  Publisher – provider of potentially unbounded number of sequenced elements, according to Subscriber(s) demand. Publisher.subscribe(Subscriber) => onSubscribe onNext* (onError | onComplete)?  Subscriber – calls Subscription.request(long) to receive notifications  Subscription – one-to-one Subscriber ↔ Publisher, request data and cancel demand (allow cleanup).  Processor = Subscriber + Publisher
  • 25. ES7 Observable Spec (RxJS 5) 25 interface Observable { constructor(subscriber : SubscriberFunction); subscribe(observer : Observer) : Subscription; subscribe(onNext : Function, onError? : Function, onComplete? : Function) : Subscription; [Symbol.observable]() : Observable; static of(...items) : Observable; static from(iterableOrObservable) : Observable; } interface Subscription { unsubscribe() : void; get closed() : Boolean; }
  • 26. 26 RxJS – JS ReactiveX (Reactive Extensions) [http://reactivex.io, https://github.com/ReactiveX]  ReactiveX is a polyglot library for composing asynchronous event streams (observable sequences).  It extends the observer pattern by declarative composition of functional transformations on events streams (e.g. map-filter- reduce, etc.)  Abstracs away low-level concerns like concurrency, synchronization, and non-blocking I/O.  Follows the next - error - completed event flow  Allows natural implementation of Redux design pattern  Alternative (together with promises) for solving “callback hell” problem
  • 31. Hot and Cold Event Streams 31  PULL-based (Cold Event Streams) – Cold streams are streams that run their sequence when and if they are subscribed to. They present the sequence from the start to each subscriber.  PUSH-based (Hot Event Streams) – Hot streams emit values independent of individual subscriptions. They have their own timeline and events occur whether someone is listening or not. An example of this is mouse events. A mouse is generating events regardless of whether there is a subscription. When subscription is made observer receives current events as they happen.
  • 32. Converting Cold to Hot Stream 32
  • 33. Flux Design Pattern Source: Flux in GitHub, https://github.com/facebook/flux, License: BSD 3-clause "New" License
  • 34. Linear flow: Source: @ngrx/store in GitHub, https://gist.github.com/btroncone/a6e4347326749f938510 Redux Design Pattern
  • 35. Source: RxJava 2 API documentation, http://reactivex.io/RxJava/2.x/javadoc/ Redux == Rx Scan Opearator
  • 36. Source: RxJS docs, https://github.com/ReactiveX/rxjs/blob/master/doc/tutorial/applications.md Redux in Plain RxJS import Immutable from 'immutable'; import someObservable from './someObservable'; import someOtherObservable from './someOtherObservable'; var initialState = { foo: 'bar' }; var state = Observable.merge( someObservable, someOtherObservable ).scan((state, changeFn) => changeFn(state), Immutable.fromJS(initialState)); export default state;
  • 37. Source: RxJS docs, https://github.com/ReactiveX/rxjs/blob/master/doc/tutorial/applications.md Redux in Plain RxJS state.js: import Immutable from 'immutable'; import someObservable from './someObservable'; import someOtherObservable from './someOtherObservable'; var initialState = { foo: 'bar' }; var state = Observable.merge( someObservable, someOtherObservable ).scan((state, changeFn) => changeFn(state), Immutable.fromJS(initialState)); export default state;
  • 38. Redux in Plain RxJS client.js: import state from './state'; state.subscribe(state => { document.querySelector('#text').innerHTML = state.get('foo'); }); Source: RxJS docs, https://github.com/ReactiveX/rxjs/blob/master/doc/tutorial/applications.md
  • 39. NGRX: Reactive Extensions for Angular  core – core functionality for the ngrx platform  store – RxJS powered state management for Angular applications, inspired by Redux  router-store – bindings to connect the Angular Router to @ngrx/store  effects – side effect model for @ngrx/store  db – RxJS powered IndexedDB for Angular apps  notify – Web Notifications powered by RxJS for Angular  store-devtools, store-log-monitor - dev tools, monitoring  example-app – example app showcasing ngrx platform
  • 40. Bootstraping NGRX App  In app.module.ts: @NgModule({ imports: [ StoreModule.provideStore(reducer), RouterStoreModule.connectRouter(), StoreDevtoolsModule.instrumentOnlyWithExtension(), EffectsModule.run(BookEffects), EffectsModule.run(CollectionEffects), DBModule.provideDB(schema), ... ] ...
  • 41. NGRX: Defining State & Reducers  in root.reducer.ts: export interface RootState { router: fromRouter.RouterState; ui: fromUi.State; users: fromUsers.State; tests: fromTests.State; } export const reducers: ReducersMap = { router: fromRouter.routerReducer, ui: fromUi.reducer, users: fromUsers.reducer, tests: fromTests.reducer };
  • 42. NGRX: Composing Root Reducer  in root.reducer.ts: const developmentReducer: ActionReducer<S> = compose(storeFreeze, combineReducers)(reducers); const productionReducer: ActionReducer<S> = combineReducers(reducers); export function rootReducer(state: any, action: any) { if (environment.production) { return productionReducer(state, action) } else { return developmentReducer(state,action) } } Store Middleware Composition Needs to be statically importable by AOT
  • 43. NGRX Selectors  A selector function is a factory for mapping functions.  Returned function maps from larger state tree into a feature substate tree (destructing the larger state).  Selectors are used with the `select` ngrx Store operator. Following example shows selector selecting the `users` sub-state: class ClientComponent { constructor(store$: Observable<State>) { this.usersState$ = store$.select(getUsersState); } }
  • 44. Composing User Selectors  in users/user.selectors.ts: // User state selectors export const getEntities = (state: State) => state.entities; export const getIds = (state: State) => state.ids; export const getAll = createSelector(getEntities, getIds, (entities, ids)=>{ return ids.map(id => entities[id]); }); // Root state selectors export const getUsersState = (state: RootState) => state.users; export const getUsers = createSelector(getUsersState, getAll);
  • 45. Using Reselect  in users/user.selectors.ts: // User state selectors export const getEntities = (state: State) => state.entities; export const getIds = (state: State) => state.ids; export const getAll = createSelector(getEntities, getIds, (entities, ids)=>{ return ids.map(id => entities[id]); }); // Root state selectors export const getUsersState = (state: RootState) => state.users; export const getUsers = createSelector(getUsersState, getAll);
  • 46. Computing Derived Data: Reselect  Selectors can compute derived data, allowing Redux to store the minimal possible state.  Selectors are efficient. A selector is not recomputed unless one of its arguments change.  Selectors are composable. They can be used as input to other selectors.  Works correctly only when combined with immutability.
  • 47. Computing Derived Data: Reselect import { createSelector } from 'reselect' const getVisibilityFilter = (state) => state.visibilityFilter const getTodos = (state) => state.todos export const getVisibleTodos = createSelector( [ getVisibilityFilter, getTodos ], (visibilityFilter, todos) => { switch (visibilityFilter) { case 'SHOW_ALL': return todos case 'SHOW_COMPLETED': return todos.filter(t => t.completed) case 'SHOW_ACTIVE': return todos.filter(t => !t.completed) }});
  • 48. Can You Spot the Problem Here? const isFirstTodoCompleteSelector = createSelector( state => state.todos[0], todo => todo && todo.completed) export default function todos(state = initState, action) { switch (action.type) { case COMPLETE_ALL: const allMarked = state.every(todo => todo.completed) return state.map(todo => { todo.completed = !allMarked return todo }) default: return state }}
  • 49. Can We Memoize without Reselect?  In users/components/user-list.component.ts: public ngOnInit() { this.store.dispatch(this.userActions.loadUsers()); this.subscription = this.selectedId$ .filter(id => !!id) .distinctUntilChanged() .subscribe(id => this.store.dispatch( go(['users', id])));
  • 51. State Normalization / Denormalization [http://redux.js.org/docs/recipes/reducers/NormalizingStateShape.html]  When a piece of data is duplicated in several places, it becomes harder to make sure that it is updated appropriately  Nested data means that the corresponding reducer logic has to be more nested or more complex. In particular, trying to update a deeply nested field can become very ugly very fast.  Since immutable data updates require all ancestors in the state tree to be copied and updated as well, an update to a deeply nested data object could force totally unrelated UI components to re-render even if the data they're displaying hasn't actually changed.
  • 52. Example: Users State Normalization export interface State { ids: IdentityType[]; entities: { [id: string]: User }; selectedUserId: IdentityType | null; loading: boolean; }; export const initialState: State = { ids: [], entities: {}, selectedUserId: null, loading: false }; export function usersReducer(state = initialState, action: Action): State { switch (action.type) { ...
  • 53. IndexedDB  IndexedDB is a low-level API for client-side storage of significant amounts of structured data (key-value pairs), including files/blobs.  API uses indexes to enable high-performance searches of this data. Web Storage - useful for smaller data.  IndexedDB is built on a transactional database model – everything you do in IndexedDB always happens in the context of a transaction.  The IndexedDB API is mostly asynchronous – you have to pass a callback function.  IndexedDB uses DOM events to notify you when results are available - type prop ("success" or "error").
  • 54. Example: @Effect and IndexedDB constructor(private actions$: Actions, private db: Database) { } @Effect({ dispatch: false }) openDB$: Observable<any> = defer(() => { return this.db.open('books_app'); }); @Effect() loadCollection$: Observable<Action> = this.actions$ .ofType(collection.LOAD) .startWith(new collection.LoadAction()) .switchMap(() => this.db.query('books').toArray() .map((books: Book[]) => new collection.LoadSuccessAction(books)) .catch(error => of( new collection.LoadFailAction(error))) );
  • 55. @Effect() addBookToCollection$: Observable<Action> = this.actions$ .ofType(collection.ADD_BOOK) .map((action: collection.AddBookAction) => action.payload) .mergeMap(book => this.db.insert('books', [ book ]) .map(() => new collection.AddBookSuccessAction(book)) .catch(() => of( new collection.AddBookFailAction(book))) ); Example: @Effect and IndexedDB
  • 56. @Effect() removeBookFromCollection$: Observable<Action> = this.actions$ .ofType(collection.REMOVE_BOOK) .map((action: collection.RemoveBookAction) => action.payload) .mergeMap(book => this.db.executeWrite('books', 'delete', [book.id]) .map(() => new collection.RemoveBookSuccessAction(book)) .catch(() => of( new collection.RemoveBookFailAction(book))) ); Example: @Effect and IndexedDB
  • 57. export interface RootState { ui: fromUi.State; router: fromRouter.RouterState; } export interface ReducersMap { [key: string]: ActionReducer<any>; } const reducers: ReducersMap = { ui: fromUi.reducer, router: fromRouter.routerReducer }; const devProdReducers: ReducersMap = { developmentReducer: compose(storeFreeze, combineReducers)(reducers), productionReducer: combineReducers(reducers) } How to Lazy Load Reducers? - I
  • 58. export function addReducer<S>(name: string, reducer: ActionReducer<S>): void { reducers[name] = reducer; devProdReducers['developmentReducer'] = compose(storeFreeze, combineReducers)(reducers); devProdReducers['productionReducer'] = combineReducers(reducers); } export function rootReducer(state: any, action: any) { if (environment.production) { return devProdReducers.productionReducer(state, action) } else { return devProdReducers.developmentReducer(state,action) } } How to Lazy Load Reducers? - II This works happily with AOT!
  • 59.  in lazy loaded module (users/user.module.ts): @NgModule({ ... }) export class UserModule { constructor() { addReducer<UserState>('users', usersReducer); } } export interface RootState extends OldRootState { users: UserState; }  Then everywhere in lazy loaded module import augmented RootState from that lazy loaded module (from users/user.module.ts, not from root.reducer.ts). Adding New Lazy Loaded Reducer
  • 60. Where to Find the Demo Code? 60 Angular and NGRX demos are available @GitHub: https://github.com/iproduct/course-angular  ipt-knowledge-manager – NGRX, Reselect, RxJS @Effects, modules lazy loading, AOT  angular2-change-detection-demos – modified from https://github.com/thoughtram/angular2-change- detection-demos  ngrx-example-app – NGRX official demo from https://github.com/ngrx/example-app, IndexedDB
  • 61. Thank’s for Your Attention! 61 Trayan Iliev CEO of IPT – Intellectual Products & Technologies http://iproduct.org/ http://robolearn.org/ https://github.com/iproduct https://twitter.com/trayaniliev https://www.facebook.com/IPT.EACAD https://plus.google.com/+IproductOrg