0

We are currently building a large software system with Angular 12. I was wondering which direction to take concerning best practices for working with observable data.

The problem

We have a lot of user data to read and manipulate in the software, which gets used in a lot of routes as well.

In The first approach you would create a local object of your data and go further from there. The observable is private.

In The second approach you directly work on the current value of the Observable. The observable is public.

It is not only the initialization and the use in the HTML template. But also manipulating like sorting order, removing and adding values. In my first impressions the second approach is more reliable, preventing double values in my observable, etc. Also, this way I do not have to subscribe on every page component to the different values. Which means less code.

The question

We need to decide as a team which approach to take throughout the software. What is considered the best-practice behavior in terms of structure and/or performance, and why?

First approach

The approach I was using at first was to subscribe to my observable data like this:

export class FavoritesComponent implements OnInit {
  favorites: Favorite[] = this.userService.userFavorites$.value;
  constructor(
    private userService: UserService,
  ) {

    // Subscribe to the favorites
    this.userService.userFavorites$.subscribe((favorites: Favorite[]) => {
        this.favorites = favorites;
    });
  }

From here, all my manipulations are getting done in this.favorites. For example in my favorites.component.html:

<div *ngFor="let favorite of favorites">
    <app-favorite-card [favorite]="favorite"></app-favorite-card>
</div>

Manipulating items (change order):

...
const itemMove = this.favorites.splice(from, 1)[0];
this.favorites.splice(to, 0, itemMove);
this.userService.userFavorites$.next(this.favorites); // update the observable

Second approach

The second approach is to directly read and manipulate from/to the observable.

export class FavoritesComponent implements OnInit {
  constructor(
    public userService: UserService,
  ) {

  }

In my favorites.component.html:

<div *ngFor="let favorite of this.userService.userFavorites$.value">
    <app-favorite-card [favorite]="favorite"></app-favorite-card>
</div>

Manipulating items (change order):

...
const itemMove = this.userService.userFavorites$.value.splice(from, 1)[0];
this.userService.userFavorites$.value.splice(to, 0, itemMove);

Sidenote

You can ignore unsubscribing, I let this out on purpose here.

Stef Van Looveren
  • 302
  • 1
  • 5
  • 15
  • I don't think it's a good idea to expose your subjects, they should be private. You can have a public property of type `Observable` and return `subject.asObservable()`. When you need to update the value in that subject, you create a public method to be called from the outside that does the `.next()` call. – Octavian Mărculescu Mar 22 '22 at 12:33
  • Hi Octavian. Thanks, but what is the problem with exposing them as public? I do not see a potential risk in it... – Stef Van Looveren Mar 22 '22 at 12:36
  • It is easier to keep in check and to avoid unwanted behaviors, like closing the subject prematurely for example. Have a look [here](https://stackoverflow.com/questions/60342665/private-subject-vs-public-readonly-subject-in-shared-services) for more context. Keep in mind that you want to put your team in the pit of success and make it hard for them to make mistakes. That's why private subjects is a good idea (imho). – Octavian Mărculescu Mar 22 '22 at 12:44
  • You should also be aware that these hot observables you create out of subjects must be also unsubscribed if you don't use them exclusively with the `async` pipe. Like in the `FavoritesComponent` where you subscribe to `userFavorites$`, you should also unsubscribe inside `onDestroy`. – Octavian Mărculescu Mar 22 '22 at 12:53
  • Indeed. I didn't add unsubscribing methods on purpose here. And thanks for answering. Still not totally convinced about the use of private vs public though... Works like a charm and is not difficult to apply on a team level. – Stef Van Looveren Mar 22 '22 at 13:00

0 Answers0