Signals are easily accessible in every level of an angular app while RxJs observables require level of complexity to share data between components.
In this article,e we will see a simple application example with two approaches. signals and RxJS observables.
While signals have an easy learning curve, RxJS with All the operators has a steep learning curve. Let’s see an example of an application feature to understand the differences between using observables vs signals.
Side Note: I recommend reading my articles “Introduction to Signals” and “RxJS: What and Why”, It will help you understand more about signals and RxJS observables before this example.
In this example we will use a very simple example, we will create a counter, the counter will start from zero, and by clicking a button we will increment the country by one.
This is the RxJS version:
import { Component } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { BehaviorSubject, take } from 'rxjs';
import 'zone.js';
@Component({
selector: 'app-root',
template: `
<div>Count: {{count$ | async}}</div>
<button (click)="counter()">Counter</button>
`,
})
export class App {
count$ = new BehaviorSubject(0);
counter() {
let latestCount = 0;
this.count$.pipe(take(1)).subscribe((x) => (latestCount = x));
this.count$.next(latestCount + 1);
}
}
Check the example here
This is the signal version:
import { Component, signal } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import 'zone.js';
@Component({
selector: 'app-root',
standalone: true,
template: `
Count: {{count()}}
`,
})
export class App {
count = signal(0);
counter() {
this.count.update((cou) => cou + 1);
}
}
Check the example here
With the RxJS example, we used BehaviorSubject and gave it an initial value of zero. for the count function, we subscribed to the observable with the pipe and take operator and used next to trigger the value of count. in the template, we used the async pipe to display the value of the observable in the browser.
With the signal example, we created a signal and gave it an init value of zero. for the count function, all we had to do was to use the update method which exists on signals and in the template there was no need to use pipe since it is a signal.
The advantages of signals over observables are very clear, even with very simple examples,:
- We don’t have to subscribe
- We don’t have to pass the async pipe
- It is more simplistic and elegant