RxJS Mastery
Что мы тут делать собрались?
Agenda
- What is RxJS
- Major Entities
- Creational Operators
- Custom Operators
- Mapping
- Filtering
- Rate Limiting
- Transformation
- Error Handling
- Combination
- Multicasting
- Schedulers
- Hidden RxJS Operators
Practice

What is RxJS
Push vs Pull

Why RxJS Important
Major Entities:
- Observables
- Observers
- Subscriptions
- Subscribers
- Subjects
Observables
Observers
Subscriptions
Subscribers
Subjects
How to create
Observable?
new Observable((observer: Observer<number>) => {
observer.next(0);
observer.complete();
observer.error(new Error('WTF?'));
});
Task 1
Create an Observable that emits 10 random values then completes and may accidentially throw an error.
const subscription: Subscription = new Observable(...);
subscription.unsubscribe();
Creational Operators
of(10, 20, 30); // 10, 20, 30
from([1,2,3,4,5]); // 1,2,3,4,5
interval(1000); // 0,1,2,3,4,5
timer(1000); // emits 0 after 1 second
fromEvent(button, 'click');
Task 2
Create a creational operator that allows subscribing to events on the DOM element. Please, make sure it's possible to unsubscribe from events. You are not allowed to use rxjs except Observable constructor.
How to create custom operators?
function myNewOperator<T, R>(source: Observable<T>): Observable<R> {
return new Observable((observer: Observer) => {
const subscription = source.subscribe({
next: (x) => observer.next(x),
complete: (e) => observer.complete(e),
error: e => observer.error(e),
});
return subscription;
});
}
function myNewOperator<T, R>(source: Observable<T>): Observable<R> {
...
}
from([1,2,3,4,5])
.pipe(
myNewOperator,
)
.subscribe();
function myNewOperator<T, R>(source: Observable<T>): Observable<R> {
return new Observable((observer: Observer) => {
const subscription = source.subscribe({
next: (x) => observer.next(x),
complete: (e) => observer.complete(e),
error: e => observer.error(e),
});
return subscription;
});
}
function myNewOperator<T, R>(source: Observable<T>): Observable<R> {
return new Observable((observer: Observer) => {
return source.subscribe({
next: (x) => observer.next(x),
complete: (e) => observer.complete(e),
error: e => observer.error(e),
});
});
}
function myNewOperator<T, R>(source: Observable<T>): Observable<R> {
return new Observable((observer: Observer) => {
return source.subscribe(observer);
});
}
Filtering Operators
take();
take();
interval(1000)
.pipe(
take(5),
)
.subscribe(() => {});
take();
stream$
.pipe(
take(1),
)
.subscribe(() => {});
take();
fromEvent(document, 'click')
.pipe(
take(1),
)
.subscribe(() => {});
take();
this.store
.pipe(
select('count'),
take(1),
)
.subscribe(() => {});
takeUntil();
takeUntil();
const timer$ = timer(5000);
interval(1000)
.pipe(
takeUntil(timer$),
)
.subscribe(() => {});
takeUntil();
class Component implements OnInit, OnDestroy {
private destroy$ = new Subject();
ngOnInit(): void {
stream$
.pipe(
takeUntil(this.destroy$),
)
.subscribe(() => {});
}
ngOnDestroy(): void {
this.destroy$.next();
}
}
takeUntil();
mousedown$
.pipe(
mergeMap(_ => {
return mousemove$.pipe(
// Do Something here
map(),
// Do until mouseup
takeUntil(mouseup$)
);
})
)
.subscribe();
takeWhile();
skip();
skipUntil();
skipWhile();
Transformation Operators
switchMap();
switchMap(); - countdown
import { interval, fromEvent, merge, empty } from 'rxjs';
import { switchMap, scan, takeWhile, startWith, mapTo } from 'rxjs/operators';
const COUNTDOWN_SECONDS = 10;
// elem refs
const remainingLabel = document.getElementById('remaining');
const pauseButton = document.getElementById('pause');
const resumeButton = document.getElementById('resume');
// streams
const interval$ = interval(1000).pipe(mapTo(-1));
const pause$ = fromEvent(pauseButton, 'click').pipe(mapTo(false));
const resume$ = fromEvent(resumeButton, 'click').pipe(mapTo(true));
const timer$ = merge(pause$, resume$)
.pipe(
startWith(true),
switchMap(val => (val ? interval$ : empty())),
scan((acc, curr) => (curr ? curr + acc : acc), COUNTDOWN_SECONDS),
takeWhile(v => v >= 0)
)
.subscribe((val: any) => (remainingLabel.innerHTML = val));
concatMap();
mergeMap();
exhaustMap();
What the difference?
RxJS Mastery
By Nikita Poltoratsky
RxJS Mastery
- 528