Commit 6a16ae06 authored by micha's avatar micha
Browse files

progress

parent 95b07229
......@@ -13,6 +13,7 @@
![](./assets/images/Reactive-architecture-and-ux-patterns_secondary_angular_michael-hladky.png)
<!-- Course Description Text -->
## Overview
Welcome to my course! My name is Michael and I will lead you through this course.
......@@ -21,7 +22,7 @@ The title of this course is reactive architecture and UX patterns.
As those are pretty broad terms let be elaborate a bit on the scope and target audience.
### Level of this Course
## Level of this Course
First the level. For this course, you definitely need some fundamental knowledge about RxJS,
......@@ -32,10 +33,7 @@ If this is not the case no big deal. As this, in an online course, you can consu
It's all about fun and explores new things, so the most important to enjoy! :)
### Content and Learning Goals
![](./assets/images/Reactive-architecture-and-ux-patterns_overview_angular_michael-hladky.png)
## Content and Learning Goals
This course starts with the fundamentals of the different operator groups we will use,
and points out some interesting details.
......@@ -43,24 +41,29 @@ and points out some interesting details.
With that in mind, we will start to work on our first patterns.
Exercises we will master are:
- State derivation and update behaviour
- Combining streams
- Overview of combination the operators
- HTTP fetching and with `forkJoin`
- Avoid over-fetching by introducing state into the Http service
- Continuously deriving state with `combineLatest`
- Reduce computations and understand data normalization
- Opt-In Updates and `withLatestFrom`
- Deriving state from HTTP calls
- Prevent over fetching with simple Http Caching
- Editing and user-controlled opt-In updates
- Optimize View updates and Performance
- Comparison of the combination patterns
- Reactive State-Management
- State aggregation
- State selection
- Architecture Patterns
- Higher-Order Observables
- Overview of the different flattening strategies (merge, concat, exhaust, switch)
- Model vs ViewModel
- Sharing state and instances
- Lazy-ness and component initialization
- Immutability and gotchas in operators
- Higher-Order Operators
- Overview of the different flattening strategies
(merge, concat, exhaust, switch)
- Usage in the user Interface
- Usage in business logic or data layer interaction like effects/epic of REDUX
- Error-Handling
- Resilience and Error-Handling
- HTTP error handling
- In-depth understanding of error handling
- How to encapsulate error-prone code
- Offline caching and polling with exponential backoff
- Comparison of the different retry & repeat mechanisms
......
......@@ -10,8 +10,9 @@ _Over-fetching HTTP requests visualized_
This is a result of wrong state-management. To face this problem, we need to store the results of the HTTP Requests in
a shared cache. We can put this behavior inside a `Service` in order to share our state accross multiple `Components`.
![Shared data store visualized](./assets/images/Reactive-architecture-and-ux-patterns_angular_http-caching_michael-hladky.png)
_Shared data store visualized_
![](./assets/images/Reactive-architecture-and-ux-patterns_angular_http-caching_michael-hladky.png)
For this exercise we introduce a very basic HTTP cache solution by using a `BehaviorSubject` as a shared data store. Instead
of binding `Components` directly to HTTP Requests, we will feed the data store with the results and provide
......@@ -78,7 +79,7 @@ constructor(...) {
## Exercise
Eliminate the HTTP requests from the `Component` by making use of the shared Observables `posts$` and `comments$`.
Eliminate the HTTP requests from the `Component` any make use of the shared Observables `posts$` and `comments$`.
Even though the data in our store gets updated properly, the `Component` won't be able to display the list of
`BlogPost` anymore.
This is because `posts$` and `comments$` do not `complete`. Since `forkJoin` relies on its sources to complete, it won't
......
......@@ -2,13 +2,14 @@
In the previous example we learned how to combine multiple HTTP Requests into one stream with `forkJoin`.
Often operators are special forms or sub forms of other operators.
If we take a look at the overview of combination patterns we realize that tow of them look very similar, forkJoin and combine.
If we take a look at the overview of combination patterns we realize that two of them look very similar, forkJoin and combine.
Both combine the values of the source Observables to one emission, but `combineLatest` in comparison to `forkJoin` does not rely
on all sources to complete. Thus allowing us to process ongoing Observables. If any of the sources emits **a new value**, the
result will update to the **latest values** of each source.
![Combination pattern combine and forkJoin](./assets/images/Reactive-architecture-and-ux-patterns_angular_combination-operators-forkJoin-vs-combine_michael-hladky.png)
![forkJoin no emission if not all complete](./assets/images/Reactive-architecture-and-ux-patterns_angular_combination-operators-forkJoin-vs-combine_michael-hladky.png)
_forkJoin no emission if not all complete_
An example of processing ongoing Observables with `combineLatest`:
......@@ -25,17 +26,33 @@ result$
console.log(result) // [0,0], [1, 10], [2, 20], [3, 30], ...
})
```
The visual representation of the above example:
## Behavior
![combineLatest - inner ongoing](assets/images/Reactive-architecture-and-ux-patterns_angular_combination-operators-combineLatest-inner-ongoing_michael-hladky.png)
_combineLatest - inner ongoing_
`combineLatest` completes when all sources `complete`.
![combineLatest - inner complete all](./assets/images/Reactive-architecture-and-ux-patterns_angular_combination-operators-combineLatest-inner-complete_michael-hladky.png)
_combineLatest - inner complete all_
If an internal Observable errors, the resulting Observable also errors.
![combineLatest - inner error](./assets/images/Reactive-architecture-and-ux-patterns_angular_combination-operators-combineLatest-inner-error_michael-hladky.png)
_combineLatest - inner error_
## 💡 Gotcha(s)!
Be careful, `combineLatest` will emit it's first value after **all** sources emitted at least one value or completed.
Be careful, `combineLatest` will emit it's first value after **all** sources emitted at least one value.
This can result in situations where no value ever gets emitted.
```Typescript
import { interval, combineLatest, NEVER } from 'rxjs';
import { map } from 'rxjs/operators';
const source1$ = NEVER; // neither emitting, nor completing observable
const source2$ = interval(1000).pipe(map(i => i * 10)); // ongoing, never completing source
const source2$ = interval(1000); // ongoing, never completing source
const result$ = combineLatest([source1$, source2$]);
result$
......@@ -44,17 +61,12 @@ Be careful, `combineLatest` will emit it's first value after **all** sources emi
})
```
![combineLatest - inner ongoing](assets/images/Reactive-architecture-and-ux-patterns_angular_combination-operators-combineLatest-inner-ongoing_michael-hladky.png)
![combineLatest - inner complete](./assets/images/Reactive-architecture-and-ux-patterns_angular_combination-operators-combineLatest-never-emits_michael-hladky.png)
_combineLatest - inner complete_
Even if some sources `complete`, we are able to process future values from other ongoing Observables while keeping the
last emission of the completed ones.
![combineLatest - inner complete](./assets/images/Reactive-architecture-and-ux-patterns_angular_combination-operators-combineLatest-inner-complete2_michael-hladky.png)
_combineLatest - inner complete_
`combineLatest` completes when all sources `complete`.
![combineLatest - inner complete all](./assets/images/Reactive-architecture-and-ux-patterns_angular_combination-operators-combineLatest-inner-complete_michael-hladky.png)
If an internal Observable errors, the resulting Observable also errors.
![combineLatest - inner error](./assets/images/Reactive-architecture-and-ux-patterns_angular_combination-operators-combineLatest-inner-error_michael-hladky.png)
......@@ -21,6 +21,7 @@ We have 2 different types, operators and creators functions.
The operators of the listed functions always have the following signature:
`(Observable<T>) => (Observable<R>) => Observable<[T, R]>`
In version 7 of RxJS there was a refactoring.
In version `7` of RxJS there was a refactoring.
The operator versions of `zip` and `combineLatest` got deprecated and the
new operators `zipWith` and `combineLatestWith` got introduced.
......@@ -9,7 +9,7 @@ In this very example we will utilize the `forkJoin` operator.
On first sight it is a perfect match for combining HTTP Requests since it waits until all
combined operators `complete` before emitting a result.
## Example
## Behavior
The below example showcases a very simple case using the `forkJoin` operator.
We make use of the `of` creation function (passing a singe value), as its emission pattern is very similar to an HTTP request.
......@@ -31,12 +31,14 @@ result$
The visual representation of the above example:
![forkJoin http calls](./assets/images/Reactive-architecture-and-ux-patterns_angular_combination-operators-forkJoin-http_michael-hladky.png)
_forkJoin http calls_
The gray boxes at the bottom of the operator scope symbolize a cache which stores the last emitted value of each included Observable.
If any of the sources raises an `error`, it gets forwarded, and the resulting Observable errors.
![forkJoin error](./assets/images/Reactive-architecture-and-ux-patterns_angular_combination-operators-forkJoin-error_michael-hladky.png)
_forkJoin error_
## 💡 Gotcha(s)!
......@@ -47,7 +49,9 @@ As stated above, the `forkJoin` creation function waits until every source raise
This example shows how `forkJoin` only emits the last value after all sources `completed`.
![forkJoin all complete last](./assets/images/Reactive-architecture-and-ux-patterns_angular_combination-operators-forkJoin-emit-all-last_michael-hladky.png)
_forkJoin all complete last_
Here you can see how `forkJoin` will never emit any value, because `a$` does not `complete`.
![forkJoin no emission if not all complete](./assets/images/Reactive-architecture-and-ux-patterns_angular_combination-operators-forkJoin-emit-after-all-complete_michael-hladky.png)
_forkJoin no emission if not all complete_
......@@ -9,11 +9,11 @@ Imagine a message feed like _twitter_ where new arriving _tweets_ first inform t
the feed.
In this scenario, users are able to _opt-in_ for updates.
![current solution: instant updates visualized](./assets/images/Reactive-architecture-and-ux-patterns_angular_instant-updates_michael-hladky.png)
_current solution: instant updates visualized_
![](./assets/images/Reactive-architecture-and-ux-patterns_angular_instant-updates_michael-hladky.png)
![desired solution: opt-in updates visualized](./assets/images/Reactive-architecture-and-ux-patterns_angular_opt-in-updates_michael-hladky.png)
_desired solution: opt-in updates visualized_
![](./assets/images/Reactive-architecture-and-ux-patterns_angular_opt-in-updates_michael-hladky.png)
For this exercise we have to extend our `Component` with extra functionalities.
......@@ -24,7 +24,6 @@ export class StartWithLatestFromComponent {
numNewItems$: Observable<number>; // the derived number of new items available for display
feed$: Observable<BlogPost[]>; // the new feed to display. use blog$ and optIntListClick$ to calculate
}
```
## Exercise
......
......@@ -36,7 +36,6 @@ import { BlogBasicService, BlogPost, toBlogPosts } from 'shared';
</mat-list-item>
</mat-list>
</div>
</div>
`,
styles: [
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment