RxJS discrete notes

Anh-Thi Dinh
Documentation
  • Learn RxJS ← well explained but not always up-to-date
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()
👉 learnrxjs
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
  1. SubjectNo initial value or replay behavior. → 1 subject (multicast) to many observers. → example
  1. AsyncSubject → Emits latest value to observers upon completion. → only show when using sub.complete()
  1. BehaviorSubjectRequires 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 or sub.subcribe()
  1. 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()
Để 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
👉 learnrxjs
1import { combineLatest } from 'rxjs';
2combineLatest([a$, b$, c$]);
Combine the “latest values” from 2 streams.
combineLatestAll (old: combineAll)
switchMap
→ "switch to a new observable"