RxJs vs. Signals: A comparison

Alain Chautard
Angular Training
Published in
3 min readAug 18, 2023

--

Angular Signals have been available since Angular 16.0.0, and one of the best ways to understand how important of a feature it is is to compare Signals to RxJs. This post will highlight several different examples.

Receiving data in a Typescript class

With RxJs Observables, we need a subscription to get our data:

myData$: Observable<Data>;

this.myData$.subscribe(d => this.data = d);

With Signals, no subscription is necessary. We call the Signal’s getter function:

myData: Signal<Data>;

this.data = this.myData();

Receiving data in an HTML template

With RxJs, we can avoid subscriptions using the async pipe in a component template:

{{ myData$ | async }}

With Signals, we still call the Signal’s getter function, just like in Typescript code:

{{ myData() }}

Creating a custom data emitter

With RxJs, we use subjects to emit data, and most of the time, BehaviorSubjects are the preferred type of subject because they hold a default value and replay the last emitted value to any new subscriber:

mySubject = new BehaviorSubject<Data>(DEFAULT_DATA);

mySubject.next(nextData);

With Signals, the approach is very similar. We use the signal function to create the Signal, and then it behaves very much like a BehaviorSubject by default:

mySignal = signal<Data>(DEFAULT_DATA);

mySignal.set(nextData);

Note that Signals have additional methods to update the current value by either mutating or deriving a new value out of the current one:

// Mutate an object in-place. No need to create a copy!
mySignal.mutate(data => data.name = "new value");

// Derive a new value out of the current one
myCounterSignal.update(value => value + 1);
Angular Certification Exam

Transforming/filtering our data

With RxJs, we use the pipe method and operators to tweak our data and apply changes to it:

name$ = myData$.pipe(
map(data => data.name)
);

name$.subscribe(d => this.data = d);

With signals, we don’t have to learn about dozens of operators. All we need is one function called computed:

nameSignal = computed(() => myData().name);

this.data = nameSignal();

Just like Observable.pipe() returns a new Observable, computed returns a new Signal.

Combining multiple data sources into one

With RxJs, combining multiple data sources into one requires operators such as switchMap, combineLatest, and more. Here is an example from this tutorial using several Observables combined into one stream of filtered data:

this.states$ = http.get<State[]>('http://localhost:8000/states');
this.filter = new FormControl('');
this.filter$ = this.filter.valueChanges.pipe(startWith(''));
this.filteredStates$ = combineLatest(this.states$, this.filter$).pipe(
map(([states, filterString]) => {
// Filtering going on here
})
);

With Signals, we can convert an Observable to a Signal with the toSignal() function. Even better, whenever any Signal used within a computed function emits a new value, the computed Signal reevaluates the function and changes the computed value accordingly. As a result, the previous RxJs code can be simplified into:

this.states = toSignal(http.get('http://...'), {initialValue: [] });
this.filter = new FormControl('');
this.filter = toSignal(this.filter.valueChanges, {initialValue: ""});
this.filteredStates = computed(() => {
let states = this.states();
let filter = this.filter();
// Filtering going on here using states and filter
});

We just removed the need for three different RxJs operators! The only catch is that Signals always have a value, so we must pass an initial value when converting Observables into Signals. On the plus side, this eliminates the need for startWith in our code, too.

Conclusion

What I love about Signals is the simplicity of the API. We can achieve a lot with just a few functions: Signal, computed, and toSignal. No subscriptions are needed, and Signals will improve change detection in Angular applications over time. All of these are excellent reasons to start using them now.

My name is Alain Chautard. I am a Google Developer Expert in Angular and a consultant and trainer at Angular Training, where I help web development teams learn and become comfortable with Angular.

If you need any help with web development, feel free to get in touch!

If you enjoyed this article, please clap for it or share it. Your help is always appreciated. You can also subscribe to my articles and my Daily Angular Newsletter to receive helpful daily tips.

--

--