Why RxJS alone doesn't guarantee declarative code
Simply pulling in RxJS doesn't automatically make your code declarative. In fact, the moment you call subscribe(), you've already shifted into imperative territory.
Being declarative with RxJS requires conscious effort.
Step 1: Set up the service
First, we'll build a service and define a variable named todo$ inside it.
The dollar sign follows a common naming convention that signals the variable holds an Observable, not the data itself.
The data retrieved from the URL will be
- routed through a pipe
- processed with the RxJS tap operator
- stored in
todo$
But if you run this as-is, you'll see no output. The console will remain empty.
Step 2: Bind the observable to a component variable
Now we switch to the component.
The crucial part is line 10:
data$ = this.todoService.todo$;
We create a local property called data$ and assign the service's observable to it so the component can reference it.
Notice that we haven't instructed Angular to subscribe or unsubscribe. There's no observer in sight either. This is where the declarative approach really pays off.
Our only intention is to render the data in the template. How Angular makes that happen is irrelevant to us.
Again, if you test this now, nothing will appear. Both the console and the template will stay blank.
That's expected — we haven't actually told Angular what we want it to do yet.
Step 3: Leverage the async pipe with the local variable
Let's move over to the template and define the goal: display the object's title in the template once the data arrives.
We achieve this with the async pipe. This pipe takes care of subscribing and unsubscribing for us, as demonstrated here:
// app.component.html
<div *ngIf="data$ | async as data">
{{ data.title }}
</div>
- First, we bind to
data$from the component. - Second, the async pipe handles the subscription and unsubscription automatically.
- Third, we use
as datato create a local variable that holds the value emitted by the observable. - Finally, that variable can be used throughout the template, just like any other property.
For a deeper dive with a side-by-side comparison of this approach versus the conventional imperative style, check out RxJS Declarative Pattern in Angular on Medium.
Feel free to share your thoughts!
