KEMBAR78
RxJS Operators - Real World Use Cases - AngularMix | PDF
OPERATORS YOU ACTUALLY CARE
ABOUT EXPLAINED FOR REAL WORLD
USE CASES
OPERATORS IN RXJS
TRACY LEE
@ladyleet
Lead, This Dot Labs, JS consulting (Angular, React, Vue, Node, Polymer)
RxJS Core Team
Google Developer Expert, Angular
Microsoft MVP
Community Rel, Node.js @ OpenJS Foundation
Women Techmakers, GDG Silicon Valley & Triangle
Modern Web Podcast
@ladyleet
THE ANATOMY OF AN OPERATOR
“operators” in Observables
import { of as observableOf } from 'rxjs';
import { map, filter } from 'rxjs/operators';
const src = observableOf(1, 2, 3, 4, 5, 6, 7);
src.pipe(
filter(x => x % 2 === 0),
map(x => x + x),
).subscribe(x => console.log(x)); // 4...8...12...
A simple map operator implementation
import { Observable } from 'rxjs';
export function map(fn) {
return (source) => new Observable(observer => {
return source.subscribe({
next(value) { observer.next(fn(value)); },
error(err) { observer.error(err); },
complete() { observer.complete(); },
});
});
}
Takes an observable & returns a new one
import { Observable } from 'rxjs';
export function map(fn) {
return (source) => new Observable(observer => {
return source.subscribe({
next(value) { observer.next(fn(value)); },
error(err) { observer.error(err); },
complete() { observer.complete(); },
});
});
}
Subscribes to the source
import { Observable } from 'rxjs';
export function map(fn) {
return (source) => new Observable(observer => {
return source.subscribe({
next(value) { observer.next(fn(value)); },
error(err) { observer.error(err); },
complete() { observer.complete(); },
});
});
}
Passes along the transformed value
import { Observable } from 'rxjs';
export function map(fn) {
return (source) => new Observable(observer => {
return source.subscribe({
next(value) { observer.next(fn(value)); },
error(err) { observer.error(err); },
complete() { observer.complete(); },
});
});
}
And sending along the other signals
import { Observable } from 'rxjs';
export function map(fn) {
return (source) => new Observable(observer => {
return source.subscribe({
next(value) { observer.next(fn(value)); },
error(err) { observer.error(err); },
complete() { observer.complete(); },
});
});
}
@ladyleet
● Flattening Operators
● Error Handling
● Completion Operators
● Subjects & Multicasting
There are 60+ operators in RxJS
map
filter
scan
THE EASIEST
OPERATORS
Deep Dive
Podcast
EXPLANATION -
Applies a reducer function over the source Observable, and
returns each intermediate result, with an optional seed value.
PRIMARY USES -
Managing state in a stream. No ngrx! You can use scan to create a
redux pattern.
scan
https://rxjs.dev/api/operators/scan
Deep Dive
Podcast
COMMON MISTAKES -
Emitting the same reference multiple times, which can cause
problems.
What you should do instead is treat your accumulated value as
immutable.
scan
https://rxjs.dev/api/operators/scan
FLATTENING
OPERATORS
FLATTENING
OPERATORS
switchMap
concatMap
mergeMap
exhaustMap
FLATTENING
OPERATORS
switchMap
concatMap
mergeMap
exhaustMap
Deep Dive
Podcast
EXPLANATION -
● Maps a value to a new observable,
● subscribes to that observable,
● unsubscribes from the previous observable it was subscribed
to.
(switchMap only subscribes to one observable at a time)
switchMap
https://rxjs.dev/api/operators/switchMap
switchMap
i$:
input$:
output$:
switchMap(fn)
fn: (v) => interval(1000).pipe(take(2))
a
i1$:
i2$:
b
A B
A
B
fn
fn
U
B
B
Deep Dive
Podcast
PRIMARY USES -
Commonly used for HTTP GET.
Great for autocompletes
Toggling between two streams
Great for animation!
switchMap
https://rxjs.dev/api/operators/switchMap
Deep Dive
Podcast
COMMON MISTAKES -
If you’re doing an HTTP POST or DELETE and a value is coming back in
the response.
If you’re relying on response from POST or DELETE in order to update
the UI, you’re only going to get response from 2nd request, and not 1st.
In these situations, use concatMap instead.
switchMap
https://rxjs.dev/api/operators/switchMap
FLATTENING
OPERATORS
switchMap
concatMap
mergeMap
exhaustMap
Deep Dive
Podcast
EXPLANATION -
Most common operator for HTTP requests.
Ensures everything happens in the order it arrived.
Takes a value from the source, maps it into a new observable, and
only runs one observable at a time until it completes. Then moves
on to the next value in the buffer.
concatMap
https://rxjs.dev/api/operators/concatMap
concatMap
i$:
input$:
output$:
concatMap(fn)
fn: (v) => interval(1000).pipe(take(2))
a
i1$:
i2$:
b
A A B B
A A
B B
fn
fn
Deep Dive
Podcast
COMMON MISTAKES -
Every single time you use concatMap, you have to make sure the observable
ends.
Never use concatMap for toggling or endless streams.
If the stream never completes, every subsequent concatMap is just going to
build up the buffer, and the other observables it’s buffering will never run.
concatMap
https://rxjs.dev/api/operators/concatMap
FLATTENING
OPERATORS
switchMap
concatMap
mergeMap
exhaustMap
Deep Dive
Podcast
EXPLANATION -
Takes every single value, maps it into an observable, and
subscribes to it.
Then, it outputs whatever is coming from those inner observables
as a single stream of values.
mergeMap
https://rxjs.dev/api/operators/mergeMap
Deep Dive
Podcast
PRIMARY USES -
Sending requests to get as many responses as fast as possible when you don’t
care about the response order.
Errors from requests: mergeMap is more useful than switchMap if you want to
know what errors come back from requests and be able to handle them.
(With switchMap, the subscription would be cancelled before the error comes
back)
mergeMap
https://rxjs.dev/api/operators/mergeMap
i$:
input$:
output$:
mergeMap(fn)
fn: (v) => interval(1000).pipe(take(2))
a
i1$:
i2$:
b
A AB B
A A
B B
fn
fn
A B
A
B
mergeMap
Deep Dive
Podcast
COMMON MISTAKES -
Using mergeMap to map to HTTP requests.
You don’t know how long a server will take to respond, and if one
request is slow and another is fast, it will end up out of order.
(If you don’t care about order, you can use it)
mergeMap
https://rxjs.dev/api/operators/mergeMap
FLATTENING
OPERATORS
switchMap
concatMap
mergeMap
exhaustMap
Deep Dive
Podcast
EXPLANATION - Conceptually, exhaustMap is the opposite of
switchMap.
Every time a value arrives, if you’re not already subscribed to a
previously mapped-to observable, exhaustMap will map it into an
observable and subscribe to that.
It will wait for the inner observable to complete or “exhaust” itself
before it allows any more new source values to be mapped into a new
inner observable.
exhaustMap
https://rxjs.dev/api/operators/exhaustMap
Deep Dive
Podcast
EXAMPLE USES -
Great for preventing double submissions.
Making sure touch drag features work properly.
exhaustMap
https://rxjs.dev/api/operators/exhaustMap
// Run a finite timer for each click, only if there is no
currently active timer
import { fromEvent, interval } from 'rxjs';
import { exhaustMap, take } from 'rxjs/operators';
const clicks = fromEvent(document, 'click');
const result = clicks.pipe(
exhaustMap(ev => interval(1000).pipe(take(5)))
);
result.subscribe(x => console.log(x));
exhaustMap example
ERROR HANDLING
ERROR HANDLING
ERROR
HANDLING
catchError
retry
retryWhen
ERROR
HANDLING
catchError
retry
retryWhen
Deep Dive
Podcast
EXPLANATION -
Prevents errors from traveling down the entire chain.
Catches errors on the Observable to be handled by returning a
new Observable or throwing an error.
When it gets an error, it maps that error into a new Observable
and replaces the original source observable with the new one.
catchError
https://rxjs.dev/api/operators/catchError
output$:
catchError
input$:
catchError(fn)
3 fn (e:any) => EMPTYn:
fn
Deep Dive
Podcast
PRIMARY USES -
Handling errors from observables by mapping them to new
observable.
Preventing HTTP errors from killing the entire observable chain.
catchError
https://rxjs.dev/api/operators/catchError
// A stream of "load button" clicks
const loadData = fromEvent(button, 'click');
// When we click "load", trigger an http get
loadData.pipe(
concatMap(() => ajax.get('/this/will/404').pipe(
catchError(err => {
// side effect, to log something happened
console.log('An error occurred loading your
stuff!');
// Return a different observable
return of({ message: 'We noticed an error' });
})
))
).subscribe(x => console.log(x));
catchError example
ERROR
HANDLING
catchError
retry
retryWhen
Deep Dive
Podcast
EXPLANATION -
If your observable errors, it will resubscribe to that observable a
specified number of times.
retry
https://rxjs.dev/api/operators/retry
Deep Dive
Podcast
PRIMARY USES -
Great in the case of an HTTP request or websocket stream where
there is network flakiness.
When it gets an error signal, it resubscribes to the original source.
retry
https://rxjs.dev/api/operators/retry
output$:
retry
input$:
retry(n)
1 uR Unsubscribes and recycles observablen:
uR
// RxJS v6+ - Retry 2 times on error
import { interval, of, throwError } from
'rxjs';
import { mergeMap, retry } from
'rxjs/operators';
const source = interval(1000);
const example = source.pipe(
mergeMap(val => {
//throw error for demonstration
if (val > 5) {
return throwError('Error!');
}
return of(val);
}),
retry example
//retry 2 times on error
retry(2)
);
const subscribe = example.subscribe({
next: val => console.log(val),
error: val => console.log(`${val}:
Retried 2 times then quit!`)
});
Deep Dive
Podcast
COMMON MISTAKES -
Using retry without an argument.
Using retry on hot observables.
(If you’re using a Subject or stateful observable, it’s not going to
reset the state of that observable, just resubscribe to it)
retry
https://rxjs.dev/api/operators/retry
catchError
retry
retryWhen
ERROR
HANDLING
Deep Dive
Podcast
EXPLANATION -
Gives you more control than retry.
Gives you an observable of errors that you can map into an
observable of notifications of when you want to retry.
retryWhen
https://rxjs.dev/api/operators/retryWhen
Deep Dive
Podcast
PRIMARY USES -
Using retry with a delay i.e incremental step back on network
failure
(if you send a network request and it fails - wait 2 seconds, try
again, if it fails, wait 4 and try, then 8 and try, etc.)
retryWhen
https://rxjs.dev/api/operators/retryWhen
output$:
retryWhen
input$:
retryWhen(fn)
1 fn (errors$) => errors$.pipe(switchMap(e => e.message === ‘X’ ? throwError(e) : of(1)))n:
fn
fn
COMPLETION
OPERATORS
COMPLETION
OPERATORS
take
takeUntil
takeWhile
first
COMPLETION
OPERATORS
take
takeUntil
takeWhile
first
Deep Dive
Podcast
EXPLANATION -
Takes the first specified number of values.
PRIMARY USES -
If you want to take the first n values from the source observable.
take
https://rxjs.dev/api/operators/take
import { interval } from 'rxjs';
import { take } from 'rxjs/operators';
const intervalCount = interval(1000);
const takeFive = intervalCount.pipe(take(5));
takeFive.subscribe(x => console.log(x));
take example
COMPLETION
OPERATORS
take
takeUntil
takeWhile
first
Deep Dive
Podcast
EXPLANATION -
Using a notifier observable to tell a source observable to
complete.
PRIMARY USES -
Declarative subscription management
takeUntil
https://rxjs.dev/api/operators/takeUntil
output$:
takeUntil
input$:
takeUntil(t$)
fromEvent(document.body, ‘click’)t$:
t$:
U
Deep Dive
Podcast
COMMON MISTAKES -
Providing the source observable with a notifier that never emits or
completes.
https://rxjs.dev/api/operators/takeUntil
takeUntil
COMPLETION
OPERATORS
take
takeUntil
takeWhile
first
Deep Dive
Podcast
EXPLANATION -
Emits values emitted by the source observable so long as each
value satisfies the given predicate…
and then completes as soon as this predicate is not satisfied.
takeWhile
https://rxjs.dev/api/operators/takeWhile
import { fromEvent } from 'rxjs';
import { takeWhile } from 'rxjs/operators';
const clicks = fromEvent(document, 'click');
const result = clicks.pipe(takeWhile(ev => ev.clientX >
200));
result.subscribe(x => console.log(x));
takeWhile example
import { fromEvent } from 'rxjs';
import { takeWhile } from 'rxjs/operators';
const clicks = fromEvent(document, 'click');
const result = clicks.pipe(takeWhile(ev => ev.clientX >
200, true));
result.subscribe(x => console.log(x));
takeWhile’s new feature (inclusive)
Deep Dive
Podcast
PRIMARY USES -
Limit for mouse movements
Progress bars
COMMON MISTAKES - Not realizing that takeWhile has to wait for a
value to arrive before it completes and using it when you actually
wanted the observable to complete after an external event.
In this scenario you should have used takeUntil.
takeWhile
https://rxjs.dev/api/operators/takeWhile
COMPLETION
OPERATORS
take
takeUntil
takeWhile
first
Deep Dive
Podcast
EXPLANATION - Emits only the first value (or the first value that meets
some condition) emitted by the source Observable, or a default value.
If no default value is provided, it will error if it does not get a first value.
PRIMARY USES -
Used when you want to get the very next value from a websocket or
from an update interval.
first
https://rxjs.dev/api/operators/first
import { fromEvent } from 'rxjs';
import { first } from 'rxjs/operators';
const clicks = fromEvent(document, 'click');
const result = clicks.pipe(first(ev => ev.target.tagName
=== 'DIV'));
result.subscribe(x => console.log(x));
first example
Deep Dive
Podcast
COMMON MISTAKES -
Not realizing that first will error if it never finds a first value, and does
not have a default value.
(In this case, you probably wanted a filter and a take)
https://rxjs.dev/api/operators/first
first
SUBJECTS AND
MULTICASTING
SUBJECTS AND
MULTICASTING
Subject
BehaviorSubject
ReplaySubject
share
shareReplay
SUBJECTS AND
MULTICASTING
Subject
BehaviorSubject
ReplaySubject
share
shareReplay
Deep Dive
Podcast
EXPLANATION -
A Subject is an observable that is also an observer.
PRIMARY USES -
Multicasting is the main use case for Subject.
Getting an observable out of user events ie button clicks.
Subject
https://rxjs.dev/api/index/class/Subject
Deep Dive
Podcast
COMMON MISTAKES - You should not just use Subject because
you don’t understand how to create an observable.
With Subjects, you do not get guaranteed teardown and memory
management that you would get with Observable.
After a Subject has errored or completed, it’s no longer usable.
https://rxjs.dev/api/index/class/Subject
Subject
SUBJECTS AND
MULTICASTING
Subject
BehaviorSubject
ReplaySubject
share
shareReplay
Deep Dive
Podcast
EXPLANATION -
A variant of Subject that requires an initial value and emits its
current value whenever it is subscribed to.
PRIMARY USES -
When you don’t want a user or system to wait to get the next
value.
BehaviorSubject
https://rxjs.dev/api/index/class/BehaviorSubject
SUBJECTS AND
MULTICASTING
Subject
BehaviorSubject
ReplaySubject
share
shareReplay
Deep Dive
Podcast
EXPLANATION - Returns a new Observable that multicasts
(shares) the original Observable.
As long as there is at least one Subscriber this Observable will be
subscribed and emitting data.
When all subscribers have unsubscribed it will unsubscribe from
the source Observable.
PRIMARY USES - Multicasting
share
https://rxjs.dev/api/operators/map
Deep Dive
Podcast
COMMON MISTAKES - Using publish or multicast when you should be using
share or shareReplay.
The reason you should use share / shareReplay is because under the hood
publish and multicast only have one instance of subject, so you can’t retry it if
there is an error.
Share automatically recycles the subject under the hood to allow you to
resubscribe to the subject.
When it errors or completes it will recycle and create a brand new instance so
it’s not completely dead. https://rxjs.dev/api/operators/share
share
Subject
BehaviorSubject
ReplaySubject
share
shareReplay
SUBJECTS AND
MULTICASTING
Deep Dive
Podcast
EXPLANATION - Same as share, but keeps the underlying ReplaySubject so the
next subscriber gets all the successful results and successful completion.
shareReplay does ref counting under the hood, but keeps a ref count of 1 to
make sure it can run to completion and to ensure the next subscriber gets the
last cached value.
PRIMARY USES - Retrieving expensive data via HTTP and you don’t want to get
it twice
shareReplay
https://rxjs.dev/api/operators/shareReplay
Deep Dive
Podcast
COMMON MISTAKES -
There is a configuration object - after the last subscriber unsubscribes,
you can actually recycle, but that is not the default behavior and it
confuses a lot of people.
You should always have at least 1 argument passed into ShareReplay.
ShareReplay without an argument will cache every single value that it
had nexted into it and replay those to new subscribers.
shareReplay
https://rxjs.dev/api/operators/shareReplay
@ladyleet
● Flattening Operators
● Error Handling
● Completion Operators
● Subjects & Multicasting
There are 60+ operators in RxJS
RxJS OPERATOR VIDEO SERIES
https://bit.ly/2IstZwM
@ladyleet
COME CONTRIBUTE!
THANK YOU
@benlesh
Angular Core Team,
RxJS Author
@michael_hladky
Google Developer
Expert, Angular
OUR
LINKS www.thisdot.co
This Dot Media
/thisdotmedia
news.thisdot.co
hi@thisdot.co
THANK YOU!

RxJS Operators - Real World Use Cases - AngularMix

  • 1.
    OPERATORS YOU ACTUALLYCARE ABOUT EXPLAINED FOR REAL WORLD USE CASES OPERATORS IN RXJS
  • 2.
    TRACY LEE @ladyleet Lead, ThisDot Labs, JS consulting (Angular, React, Vue, Node, Polymer) RxJS Core Team Google Developer Expert, Angular Microsoft MVP Community Rel, Node.js @ OpenJS Foundation Women Techmakers, GDG Silicon Valley & Triangle Modern Web Podcast
  • 3.
  • 4.
    “operators” in Observables import{ of as observableOf } from 'rxjs'; import { map, filter } from 'rxjs/operators'; const src = observableOf(1, 2, 3, 4, 5, 6, 7); src.pipe( filter(x => x % 2 === 0), map(x => x + x), ).subscribe(x => console.log(x)); // 4...8...12...
  • 5.
    A simple mapoperator implementation import { Observable } from 'rxjs'; export function map(fn) { return (source) => new Observable(observer => { return source.subscribe({ next(value) { observer.next(fn(value)); }, error(err) { observer.error(err); }, complete() { observer.complete(); }, }); }); }
  • 6.
    Takes an observable& returns a new one import { Observable } from 'rxjs'; export function map(fn) { return (source) => new Observable(observer => { return source.subscribe({ next(value) { observer.next(fn(value)); }, error(err) { observer.error(err); }, complete() { observer.complete(); }, }); }); }
  • 7.
    Subscribes to thesource import { Observable } from 'rxjs'; export function map(fn) { return (source) => new Observable(observer => { return source.subscribe({ next(value) { observer.next(fn(value)); }, error(err) { observer.error(err); }, complete() { observer.complete(); }, }); }); }
  • 8.
    Passes along thetransformed value import { Observable } from 'rxjs'; export function map(fn) { return (source) => new Observable(observer => { return source.subscribe({ next(value) { observer.next(fn(value)); }, error(err) { observer.error(err); }, complete() { observer.complete(); }, }); }); }
  • 9.
    And sending alongthe other signals import { Observable } from 'rxjs'; export function map(fn) { return (source) => new Observable(observer => { return source.subscribe({ next(value) { observer.next(fn(value)); }, error(err) { observer.error(err); }, complete() { observer.complete(); }, }); }); }
  • 10.
    @ladyleet ● Flattening Operators ●Error Handling ● Completion Operators ● Subjects & Multicasting There are 60+ operators in RxJS
  • 11.
  • 12.
    Deep Dive Podcast EXPLANATION - Appliesa reducer function over the source Observable, and returns each intermediate result, with an optional seed value. PRIMARY USES - Managing state in a stream. No ngrx! You can use scan to create a redux pattern. scan https://rxjs.dev/api/operators/scan
  • 13.
    Deep Dive Podcast COMMON MISTAKES- Emitting the same reference multiple times, which can cause problems. What you should do instead is treat your accumulated value as immutable. scan https://rxjs.dev/api/operators/scan
  • 14.
  • 15.
  • 16.
  • 17.
    Deep Dive Podcast EXPLANATION - ●Maps a value to a new observable, ● subscribes to that observable, ● unsubscribes from the previous observable it was subscribed to. (switchMap only subscribes to one observable at a time) switchMap https://rxjs.dev/api/operators/switchMap
  • 18.
    switchMap i$: input$: output$: switchMap(fn) fn: (v) =>interval(1000).pipe(take(2)) a i1$: i2$: b A B A B fn fn U B B
  • 19.
    Deep Dive Podcast PRIMARY USES- Commonly used for HTTP GET. Great for autocompletes Toggling between two streams Great for animation! switchMap https://rxjs.dev/api/operators/switchMap
  • 20.
    Deep Dive Podcast COMMON MISTAKES- If you’re doing an HTTP POST or DELETE and a value is coming back in the response. If you’re relying on response from POST or DELETE in order to update the UI, you’re only going to get response from 2nd request, and not 1st. In these situations, use concatMap instead. switchMap https://rxjs.dev/api/operators/switchMap
  • 21.
  • 22.
    Deep Dive Podcast EXPLANATION - Mostcommon operator for HTTP requests. Ensures everything happens in the order it arrived. Takes a value from the source, maps it into a new observable, and only runs one observable at a time until it completes. Then moves on to the next value in the buffer. concatMap https://rxjs.dev/api/operators/concatMap
  • 23.
    concatMap i$: input$: output$: concatMap(fn) fn: (v) =>interval(1000).pipe(take(2)) a i1$: i2$: b A A B B A A B B fn fn
  • 24.
    Deep Dive Podcast COMMON MISTAKES- Every single time you use concatMap, you have to make sure the observable ends. Never use concatMap for toggling or endless streams. If the stream never completes, every subsequent concatMap is just going to build up the buffer, and the other observables it’s buffering will never run. concatMap https://rxjs.dev/api/operators/concatMap
  • 25.
  • 26.
    Deep Dive Podcast EXPLANATION - Takesevery single value, maps it into an observable, and subscribes to it. Then, it outputs whatever is coming from those inner observables as a single stream of values. mergeMap https://rxjs.dev/api/operators/mergeMap
  • 27.
    Deep Dive Podcast PRIMARY USES- Sending requests to get as many responses as fast as possible when you don’t care about the response order. Errors from requests: mergeMap is more useful than switchMap if you want to know what errors come back from requests and be able to handle them. (With switchMap, the subscription would be cancelled before the error comes back) mergeMap https://rxjs.dev/api/operators/mergeMap
  • 28.
    i$: input$: output$: mergeMap(fn) fn: (v) =>interval(1000).pipe(take(2)) a i1$: i2$: b A AB B A A B B fn fn A B A B mergeMap
  • 29.
    Deep Dive Podcast COMMON MISTAKES- Using mergeMap to map to HTTP requests. You don’t know how long a server will take to respond, and if one request is slow and another is fast, it will end up out of order. (If you don’t care about order, you can use it) mergeMap https://rxjs.dev/api/operators/mergeMap
  • 30.
  • 31.
    Deep Dive Podcast EXPLANATION -Conceptually, exhaustMap is the opposite of switchMap. Every time a value arrives, if you’re not already subscribed to a previously mapped-to observable, exhaustMap will map it into an observable and subscribe to that. It will wait for the inner observable to complete or “exhaust” itself before it allows any more new source values to be mapped into a new inner observable. exhaustMap https://rxjs.dev/api/operators/exhaustMap
  • 32.
    Deep Dive Podcast EXAMPLE USES- Great for preventing double submissions. Making sure touch drag features work properly. exhaustMap https://rxjs.dev/api/operators/exhaustMap
  • 33.
    // Run afinite timer for each click, only if there is no currently active timer import { fromEvent, interval } from 'rxjs'; import { exhaustMap, take } from 'rxjs/operators'; const clicks = fromEvent(document, 'click'); const result = clicks.pipe( exhaustMap(ev => interval(1000).pipe(take(5))) ); result.subscribe(x => console.log(x)); exhaustMap example
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
    Deep Dive Podcast EXPLANATION - Preventserrors from traveling down the entire chain. Catches errors on the Observable to be handled by returning a new Observable or throwing an error. When it gets an error, it maps that error into a new Observable and replaces the original source observable with the new one. catchError https://rxjs.dev/api/operators/catchError
  • 39.
  • 40.
    Deep Dive Podcast PRIMARY USES- Handling errors from observables by mapping them to new observable. Preventing HTTP errors from killing the entire observable chain. catchError https://rxjs.dev/api/operators/catchError
  • 41.
    // A streamof "load button" clicks const loadData = fromEvent(button, 'click'); // When we click "load", trigger an http get loadData.pipe( concatMap(() => ajax.get('/this/will/404').pipe( catchError(err => { // side effect, to log something happened console.log('An error occurred loading your stuff!'); // Return a different observable return of({ message: 'We noticed an error' }); }) )) ).subscribe(x => console.log(x)); catchError example
  • 42.
  • 43.
    Deep Dive Podcast EXPLANATION - Ifyour observable errors, it will resubscribe to that observable a specified number of times. retry https://rxjs.dev/api/operators/retry
  • 44.
    Deep Dive Podcast PRIMARY USES- Great in the case of an HTTP request or websocket stream where there is network flakiness. When it gets an error signal, it resubscribes to the original source. retry https://rxjs.dev/api/operators/retry
  • 45.
  • 46.
    // RxJS v6+- Retry 2 times on error import { interval, of, throwError } from 'rxjs'; import { mergeMap, retry } from 'rxjs/operators'; const source = interval(1000); const example = source.pipe( mergeMap(val => { //throw error for demonstration if (val > 5) { return throwError('Error!'); } return of(val); }), retry example //retry 2 times on error retry(2) ); const subscribe = example.subscribe({ next: val => console.log(val), error: val => console.log(`${val}: Retried 2 times then quit!`) });
  • 47.
    Deep Dive Podcast COMMON MISTAKES- Using retry without an argument. Using retry on hot observables. (If you’re using a Subject or stateful observable, it’s not going to reset the state of that observable, just resubscribe to it) retry https://rxjs.dev/api/operators/retry
  • 48.
  • 49.
    Deep Dive Podcast EXPLANATION - Givesyou more control than retry. Gives you an observable of errors that you can map into an observable of notifications of when you want to retry. retryWhen https://rxjs.dev/api/operators/retryWhen
  • 50.
    Deep Dive Podcast PRIMARY USES- Using retry with a delay i.e incremental step back on network failure (if you send a network request and it fails - wait 2 seconds, try again, if it fails, wait 4 and try, then 8 and try, etc.) retryWhen https://rxjs.dev/api/operators/retryWhen
  • 51.
    output$: retryWhen input$: retryWhen(fn) 1 fn (errors$)=> errors$.pipe(switchMap(e => e.message === ‘X’ ? throwError(e) : of(1)))n: fn fn
  • 52.
  • 53.
  • 54.
  • 55.
    Deep Dive Podcast EXPLANATION - Takesthe first specified number of values. PRIMARY USES - If you want to take the first n values from the source observable. take https://rxjs.dev/api/operators/take
  • 56.
    import { interval} from 'rxjs'; import { take } from 'rxjs/operators'; const intervalCount = interval(1000); const takeFive = intervalCount.pipe(take(5)); takeFive.subscribe(x => console.log(x)); take example
  • 57.
  • 58.
    Deep Dive Podcast EXPLANATION - Usinga notifier observable to tell a source observable to complete. PRIMARY USES - Declarative subscription management takeUntil https://rxjs.dev/api/operators/takeUntil
  • 59.
  • 60.
    Deep Dive Podcast COMMON MISTAKES- Providing the source observable with a notifier that never emits or completes. https://rxjs.dev/api/operators/takeUntil takeUntil
  • 61.
  • 62.
    Deep Dive Podcast EXPLANATION - Emitsvalues emitted by the source observable so long as each value satisfies the given predicate… and then completes as soon as this predicate is not satisfied. takeWhile https://rxjs.dev/api/operators/takeWhile
  • 63.
    import { fromEvent} from 'rxjs'; import { takeWhile } from 'rxjs/operators'; const clicks = fromEvent(document, 'click'); const result = clicks.pipe(takeWhile(ev => ev.clientX > 200)); result.subscribe(x => console.log(x)); takeWhile example
  • 64.
    import { fromEvent} from 'rxjs'; import { takeWhile } from 'rxjs/operators'; const clicks = fromEvent(document, 'click'); const result = clicks.pipe(takeWhile(ev => ev.clientX > 200, true)); result.subscribe(x => console.log(x)); takeWhile’s new feature (inclusive)
  • 65.
    Deep Dive Podcast PRIMARY USES- Limit for mouse movements Progress bars COMMON MISTAKES - Not realizing that takeWhile has to wait for a value to arrive before it completes and using it when you actually wanted the observable to complete after an external event. In this scenario you should have used takeUntil. takeWhile https://rxjs.dev/api/operators/takeWhile
  • 66.
  • 67.
    Deep Dive Podcast EXPLANATION -Emits only the first value (or the first value that meets some condition) emitted by the source Observable, or a default value. If no default value is provided, it will error if it does not get a first value. PRIMARY USES - Used when you want to get the very next value from a websocket or from an update interval. first https://rxjs.dev/api/operators/first
  • 68.
    import { fromEvent} from 'rxjs'; import { first } from 'rxjs/operators'; const clicks = fromEvent(document, 'click'); const result = clicks.pipe(first(ev => ev.target.tagName === 'DIV')); result.subscribe(x => console.log(x)); first example
  • 69.
    Deep Dive Podcast COMMON MISTAKES- Not realizing that first will error if it never finds a first value, and does not have a default value. (In this case, you probably wanted a filter and a take) https://rxjs.dev/api/operators/first first
  • 70.
  • 71.
  • 72.
  • 73.
    Deep Dive Podcast EXPLANATION - ASubject is an observable that is also an observer. PRIMARY USES - Multicasting is the main use case for Subject. Getting an observable out of user events ie button clicks. Subject https://rxjs.dev/api/index/class/Subject
  • 74.
    Deep Dive Podcast COMMON MISTAKES- You should not just use Subject because you don’t understand how to create an observable. With Subjects, you do not get guaranteed teardown and memory management that you would get with Observable. After a Subject has errored or completed, it’s no longer usable. https://rxjs.dev/api/index/class/Subject Subject
  • 75.
  • 76.
    Deep Dive Podcast EXPLANATION - Avariant of Subject that requires an initial value and emits its current value whenever it is subscribed to. PRIMARY USES - When you don’t want a user or system to wait to get the next value. BehaviorSubject https://rxjs.dev/api/index/class/BehaviorSubject
  • 77.
  • 78.
    Deep Dive Podcast EXPLANATION -Returns a new Observable that multicasts (shares) the original Observable. As long as there is at least one Subscriber this Observable will be subscribed and emitting data. When all subscribers have unsubscribed it will unsubscribe from the source Observable. PRIMARY USES - Multicasting share https://rxjs.dev/api/operators/map
  • 79.
    Deep Dive Podcast COMMON MISTAKES- Using publish or multicast when you should be using share or shareReplay. The reason you should use share / shareReplay is because under the hood publish and multicast only have one instance of subject, so you can’t retry it if there is an error. Share automatically recycles the subject under the hood to allow you to resubscribe to the subject. When it errors or completes it will recycle and create a brand new instance so it’s not completely dead. https://rxjs.dev/api/operators/share share
  • 80.
  • 81.
    Deep Dive Podcast EXPLANATION -Same as share, but keeps the underlying ReplaySubject so the next subscriber gets all the successful results and successful completion. shareReplay does ref counting under the hood, but keeps a ref count of 1 to make sure it can run to completion and to ensure the next subscriber gets the last cached value. PRIMARY USES - Retrieving expensive data via HTTP and you don’t want to get it twice shareReplay https://rxjs.dev/api/operators/shareReplay
  • 82.
    Deep Dive Podcast COMMON MISTAKES- There is a configuration object - after the last subscriber unsubscribes, you can actually recycle, but that is not the default behavior and it confuses a lot of people. You should always have at least 1 argument passed into ShareReplay. ShareReplay without an argument will cache every single value that it had nexted into it and replay those to new subscribers. shareReplay https://rxjs.dev/api/operators/shareReplay
  • 83.
    @ladyleet ● Flattening Operators ●Error Handling ● Completion Operators ● Subjects & Multicasting There are 60+ operators in RxJS
  • 84.
    RxJS OPERATOR VIDEOSERIES https://bit.ly/2IstZwM
  • 85.
  • 86.
    THANK YOU @benlesh Angular CoreTeam, RxJS Author @michael_hladky Google Developer Expert, Angular
  • 87.
    OUR LINKS www.thisdot.co This DotMedia /thisdotmedia news.thisdot.co
  • 88.