Observables and RxJS tutorial / FAQ

Updated:

this post is still work in progress it will be updated often in the future, trying to quickly clarify some 'reactive thinking' to Java devs

Why I have to unsubscribe?

The subscriptions can survive the components that created them.
This could create a memory leak in the application.

When I don't need to unsubscribe?

  • ActivateRoute

    The ActivatedRoute and its observables are insulated from the Router itself. The Router destroys a routed component when it is no longer needed and the injected ActivatedRoute dies with it.

  • AsynchPipe {{expression | asynch}}.

    When the component gets destroyed, the async pipe unsubscribes automatically to avoid potential memory leaks.

  • Singletons: e.g. AppComponent, Services they are instantiated only once.

  • Finite subscriptions:

  • Operators that unsubscribe themselves (usually after they complete):

    • take()
    • first()
    • debounce()
    • switchMap()
    • ...

Are Observables eager or lazy?

Lazy. Observables starts only when an observer subscribe (e.g. .subscribe()).

Promises are eager.

Are Observables synchronous or asynchronous

They can be synchronous or asynchrounous.

Promises are only asynch.

How many values are returned?

From 0 to potentially infinite values.

When my Subscriber will start to receive values?

After the subscription when the Observable will emit the next value or, in case of BehaviorSubject immediately (previous or initial value).

What is the difference between Subject, BehaviorSubject, ReplaySubject?

  • Subject : emits the values only after the subscription, it doesn't store any value. It can publish and subscribe.
  • BehaviorSubject : it stores an initial value.
    When subscribed it returns the last value emitted or the initial value.
    This is very useful if you need to load data before it's effectively used / showed.
  • ReplaySubject : it stores multiple values, it has a bufferSize property that defines the number of values stored.
    When subscribed it returns the values stored in the buffer.

How to combine 2 streams, e.g. 2 database tables by key

This case is very frequent if you are working with databases and you have to combine two streams representing a database by key.
The best option you have is combineLatest :

  • combines multiple streams
  • uses the latest emitted values
  • wait for each input stream to emit at last once
  • emits an array of values, in order, containing the result of each stream
personWithAddress$ = combineLatest( 
  this.personList$, 
  this.adressList$) 
) 

this would emit an array containing the two arrays:
[PersonList[], Adresses[]]
this value can be passed through your rxjs pipe.

Observables can manage multiple observers?

When to unsubscribe

There are multiple strategies:

  1. ngOnDestroy and Array

A very common solution is to unsubscribe when the component is destroyed.
A common practice is to store all the Subscriptions in an array and unsubscribe them in a loop forEach.

private subscriptions: Subscription[] = []; 
 
ngOnInit() { 
  this.subscriptions.push(this.yourObservables.subscribe()) 
} 
 
ngOnDestroy() { 
  this.subscriptions.forEach(subscription => subscription.unsubscribe()); 
} 

**2. Subject and takeUntil

example

Some useful operators

  • takeUntil:
  • takeWhile:**

WebApp built by Marco using SpringBoot 3.2.4 and Java 21, in a Server in Switzerland