Reactive programming
Suggested resources
- Web Rush Episode 31: RxJS Wizardry with Ben Lesh
- RxJS schedulers from outer space - Performance, animations, asynchrony at ng-conf by Michael Hladky
- A deep dive into RxJS subjects at Angular In Depth by Michael Hladky
- Learn RxJS
- Official Getting started guide
- Angular.io: Observables & RxJS
- Reactive Programming in Angular by Victor Savkin
- RxJS: Understanding Subjects by Nicholas Jamieson
- RxJS: Understanding the publish and share Operators by Nicholas Jamieson
- RxJS: How to Use refCount
- The introduction to Reactive Programming you've been missing by André Stalz
Suggested topics
- Composing asynchronous software
- Understanding operators
- "Breaking the ice"
- Reactive programming in a nutshell
- The Observer Pattern
- The building blocks of RxJS
- Observables
- Subscribers
- Subscriptions
- Subjects
- Operators
- Observables are executed lazily. They don't do anything until they have a subscriber.
- Reactive programming in more abstract terms, no RxJS specifics
- Reactive programming sweeps the intermediary states under the rug, hiding them in operators
- Reactive programming libraries
- Lingo
- Notifications (next, complete, error)
- Events/values
- Subscribers/observers, observables/streams
- Subscriptions
- Producers, consumers
- How RxJS is used by Angular
- Multicasting
share
,publish
,refCount
,multicast
,connect
, and connectable observables- Subjects
- Schedulers
- Cold, hot, warm observables
- Flattening observables
merge*
exhaust*
switch*
concat*
Reactive micro and macro architecture
Concepts and techniques coined and taught by Michael Hladky.
- Slides
- StackBlitz
- ng-conf workshop: Operate heavily dynamic UIs
- Tweet with images
- ngVikings talk: Operate heavily dynamic UI’s with RxJS
- Frontend Love workshop: RxJS Advanced Patterns Learn how to manage heavily dynamic Angular apps
Filtering and subscription management
takeWhile
vs.takeUntil
takeWhile
when you want to unsubscribe based on an event in the observable pipelinetakeUntil
when you want to unsubscribe based on another eventfilter
to filter out events based on their value- Learn RxJS: Filtering operators
Building your own observable
When to build your own observable, when not to.
Building your own operator
Use composition of existing operators over building your own.
Application/enterprise-specific operators
Usually combines a bunch of operators that are used throughout one or more applications, or even just in a few places but to make the code more readable.
Reusable operators (libraries)
Describe and test the semantics of every edge case:
- What happens when a synchronous
empty()
is passed? - What happens when an asynchronous
empty()
is passed? - What happens when a
NEVER
is passed?
When joining more than one observable:
- What happens when one is a
NEVER
and one is not?
When accepting function parameters:
- What happens when an error happens in that function?
Error handling:
- Test your custom operator in isolation
- Errors that unsubscribe
- An observable goes south and drops future subscriptions (bad)
Subscribers
Subscribers have a subscription. They are observables with a subscription tied to them. Every operator sets up one subscriber.
Subscribers have these safety semantics:
- If you call
error
orcomplete
, the subscription is teared down and an internal property call closed is flipped and make sure that you cannot callnext
,error
, orcomplete
again. - Chain of subscribers: Error in any single point - that subscriber cannot be used again which means you can't pass values through it and you've unsubscribed from the original subscription.
- Several strategies, the primary for protecting your observable from dying:
Create another observable with a flattening operator and punctuate that
observable with a
catchError
.catchError
: Listens to error channel on its subscriber and maps it to a new observable, subscribes to that and sends its output to the flattening operator and shields the main chain of subscribers from ever having error called on any of them and therefore have their subscription kept active.
Subjects
Subjects can be used for multicasting.
BehaviorSubjects
have an initial state when created, so they can be used to capture hot streamsSubjects
are for eventual values--they don't have an initial or current stateReplaySubjects
are used to replay streams
Subscriptions
Forgetting to unsubscribe will lead to memory leaks and side effects being run after the related component is destroyed.
Strategies for managing subscriptions:
takeUntil(this.destroy)
(here be dragons)Subscription#add
(tree of subscriptions) vs.SubSink
(array of subscriptions)- Manual unsubscription of every subscription
share
, publish
, refCount
, and multicast
refCount
runs teardown logic when the number of subscribers goes down to 0.
multicast
with and without a factory.
Cold, hot, warm, and shared observables
An observable is cold if a new producer is created per subscriber. This implies that the setup of the producer such as an HTTP call is performed on subscription. Because of this, cold observables are unicast.
In contrast, observables are hot if their producer is created separately from subscription, for example if an observable adds an event listener to an existing WebSocket connection. Hot observables are most often multicast.
Warm observables are hot but have lazy setup logic. They don't emit values until
they have at least one subscriber. Late subscribers might miss emitted values.
We can implement warm observables using the publish
operator to create a
connectable observable, followed by a refCount
operation to keep track of
subscribers.
Shared observables are created using the share*
operators. They act like warm
observables, except they are recreated if a subscription is created after their
completion.