Documentation
- Learn RxJS ← well explained but not always up-to-date
- Interactive diagrams of Rx Observables ← understand how things work visually
Be careful when using
lastValueFrom
and firstValueFrom
- Only use
firstValueFrom
this with observables you know will emit at least one value, OR complete.
- Only use
lastValueFrom
with observables you know will complete.
→ Most of the time, if you just get the first value from the observable, just try
firstValueFrom
!It’s better to use “Subscribe Arguments”
1// deprecated
2of([1,2,3]).subscribe(null, null, console.info); // difficult to read
3// suggested change
4of([1,2,3]).subscribe({complete: console.info});
1// deprecated
2throwError('I am an error').subscribe(null, console.error);
3// suggested change
4throwError('I am an error').subscribe({error: console.error});
1// recommended
2of([1,2,3]).subscribe((v) => console.info(v));
3// also recommended
4of([1,2,3]).subscribe({
5 next: (v) => console.log(v),
6 error: (e) => console.error(e),
7 complete: () => console.info('complete')
8})
Knowing which is triggered in
combineLatest
Theo mặc định thì ko có hàm chính thống, có thể thử
1var trigger = "";
2
3Rx.Observable
4 .combineLatest(
5 s1.pipe(tap(() => (this.trigger = 's1'))),
6 s2.pipe(tap(() => (this.trigger = 's2')))
7 ).subscribe(function(){
8 console.log("which is triggered? :", this.trigger);
9 });
distinctUntilChanged()
1// Simple usage
2source$.pipe(distinctUntilChanged()).subscribe(console.log);
3
4// Custom comparer
5source$.pipe(distinctUntilChanged((prev, curr) => prev.name === curr.name)).subscribe(console.log);
1// Using lodash's things
2import { isEqual } from 'lodash';
3source$.pipe(distinctUntilChanged(isEqual).subscribe(console.log);
toPromise
to lastValueFrom
or firstValueFrom
1// Old "toPromise()"
2public async loadCategories() {
3 this.categories = await this.service
4 .getCategories().toPromise()
5}
1// New "lastValueFrom"
2public async loadCategories() {
3 const categories$ = this.service.getCategories();
4 this.categories = await lastValueFrom(categories$);
5}
Observables
Observables represent a progressive way of handling events, async activity, and multiple values in JavaScript. Observables are really just functions that throw values. Objects called observers define callback functions for next(), error(), and complete(). ← ref
- The function we pass to
subscribe()
gets executed whenever a new value is emitted.
1const button = document.querySelector('button')
2const observable = Rx.Observable.fromEvent(button, 'click')
3observable.subscribe(event => {
4 console.log(event.target)
5})
- Should read → 6 Simple Examples Which Will Make You Love Observables (rxjs 5)
- The true power of rxjs → operators (
bufferCount(3)
← eg, 3 clicks to show random numbers) - Use any other lib with rxjs, eg. transform any Promise to Observable by
fromPromise
- Smooth handling of HTTP request → eg. if there are many requests in a short time (we need the last will be treated) → race condition → subscribe the last, unsubsribe all previous →
switchMap
- Dùng cái này để theo dõi các đối tượng liên tục!!!! ← ref vn (thật ra cũng là dịch)
- vs promise? → Everything you can do with a Promise you can do with an Observable. Everything you can do with an Observable you can't necessarily do with a Promise. (ref)
(Check the limit of promise above)
4 types of subjects
Subject
→ No initial value or replay behavior. → 1 subject (multicast) to many observers. → example
AsyncSubject
→ Emits latest value to observers upon completion. → only show when usingsub.complete()
BehaviorSubject
→ Requires an initial value and emits its current value (last emitted item) to new subscribers. → example & based on mouse clicks- Get current value? → either
sub.value
orsub.subcribe()
ReplaySubject
→ Emits specified number of last emitted values (a replay) to new subscribers.- Need specify how many values / how long you wanna store "old" values.
Subject - Expected 1 arguments, but got 0
1destroy$ = new Subject();
2constructor() {
3 this.destroy$.next(); // <-- Expected 1 arguments, but got 0.
4}
1new Subject<void>()
2// or
3this.destroy$.next(true);
.pipe()
→ read this and official doc
Để tránh import toàn bộ
rxjs/operators
, chúng ta sẽ import những operators ta cần → tuy nhiên có những lúc (ví dụ clean hệ thống), ta vẫn import nhưng không dùng → pipe dùng để nhận biết cái nào được dùng và ignore những cái imported khác!1// instead of
2var$.tap().switchMap().catchError()
1// using pipe()
2var$.pipe( tap(), switchMap(), catchError() )
combineLatest
1import { combineLatest } from 'rxjs';
2combineLatest([a$, b$, c$]);
Combine the “latest values” from 2 streams.
switchMap
→ "switch to a new observable"