web-dev-qa-db-fra.com

NgrxStore et Angular - Utilisez massivement le canal asynchrone ou abonnez-vous une seule fois dans le constructeur

Je commence à regarder ngrx Store et je vois la commodité d'utiliser le canal asynchrone Angular. En même temps, je ne suis pas sûr d'utiliser le Angular le tuyau asynchrone est massivement un bon choix.

Je fais un exemple simple. Supposons que dans le même modèle, je dois montrer différents attributs d'un objet (par exemple, une personne) qui est récupéré à partir du magasin.

Un morceau de code de modèle pourrait être

<div>{{(person$ | async).name}}</div>
<div>{{(person$ | async).address}}</div>
<div>{{(person$ | async).age}}</div>

tandis que le constructeur de classe de composant aurait

export class MyComponent {
  person$: Observable<Person>;

  constructor(
    private store: Store<ApplicationState>
  ) {
      this.person$ = this.store.select(stateToCurrentPersonSelector);
  }
.....
.....
}

Pour autant que je comprends ce code implique 3 abonnements (effectués dans le modèle via le canal asynchrone) au même observable (person$).

Une alternative serait de définir 1 propriété (person) dans MyComponent et d'avoir seulement 1 abonnement (dans le constructeur) qui remplit la propriété, comme

export class MyComponent {
  person: Person;

  constructor(
    private store: Store<ApplicationState>
  ) {
      this.store.select(stateToCurrentPersonSelector)
                .subscribe(person => this.person = person);
  }
.....
.....
}

tandis que le modèle utilise la liaison de propriété standard (c'est-à-dire sans le canal asynchrone), comme

<div>{{person.name}}</div>
<div>{{person.address}}</div>
<div>{{person.age}}</div>

Maintenant la question

Y a-t-il une différence en termes de performances entre les 2 approches? L'utilisation massive du canal asynchrone (c'est-à-dire une utilisation massive des abonnements) va-t-elle affecter l'efficacité du code?

44
Picci

Vous ne devez pas non plus composer votre application en tant que composants intelligents et de présentation.

Avantages:

  • Toute logique de buissness sur le contrôleur intelligent.
  • Un seul abonnement
  • Réutilisabilité
  • Le contrôleur de présentation n'a qu'une seule responsabilité, celle de présenter les données et ne sait pas d'où viennent les données. (couplage lâche)

Répondre à la dernière question:

L'utilisation massive du canal asynchrone affectera l'efficacité, car il s'abonnera à chaque canal asynchrone. Vous pouvez le remarquer davantage si vous appelez un service http, car il appellera la demande http pour chaque canal asynchrone.

Composant intelligent

@Component({
  selector: 'app-my',
  template: `
      <app-person [person]="person$ | async"></app-person>
`,
  styleUrls: ['./my.component.css']
})
export class MyComponent implements OnInit {

    person$: Observable<Person>;

    constructor(private store: Store<ApplicationState>) {}

    ngOnInit() {
        this.person$ = this.store.select(stateToCurrentPersonSelector);
    }

}

Composant de présentation

@Component({
  selector: 'app-person',
  template: `
    <div>{{person.name}}</div>
    <div>{{person.address}}</div>
    <div>{{person.age}}</div>
`,
  styleUrls: ['./my.component.css']
})
export class PersonComponent implements OnInit {

    @Input() person: Person;

    constructor() {}

    ngOnInit() {
    }

}

Pour plus d'informations, consultez:

37
Victor Godoy

Une autre possibilité consiste à utiliser une construction comme celle-ci:

<div *ngIf="person$ | async as per">
    <div>{{ per.name }}</div>
    <div>{{ per.address }}</div>
    <div>{{ per.age }}</div>
<div>

Bien que pour les bits de code réutilisables, il est préférable d'utiliser la méthode du composant de présentation.

Veuillez noter que cela fonctionne en angular 5, pas sûr des autres versions.

12
marxin

Vous pouvez ajouter ".share ()" à la fin de toute déclaration observable. Tous vos canaux asynchrones sur un observable partageront alors le même abonnement:

this.name$ = Observable.create(observer => {
  console.log("Subscriber!", observer);
  return observer.next("john")
}).delay(2000).share();

this.httpget$ = http.get("https://api.github.com/").share();

Plunkr démontrant: https://embed.plnkr.co/HNuq1jUh3vyfR2IuIe4X/

11
John Hamm