Software Development / JavaScript

Dyrektywa *ngIf oraz operator shareReplay, czyli jak radzić sobie z wielokrotnym wykorzystaniem observabla w templatce

Kwiecień 22, 2021 0
Podziel się:

W Angular jedną z bardziej eleganckich metod subskrypcji do strumieni jest użycie async pipe.
Dzięki temu nie potrzebujemy pamiętać, aby się odsubskrybować w metodzie ngOnDestroy i nie mamy potencjalnych wycieków pamięci.

<div class="company-address">
  <h3>Address</h3>
  <h4>{{ company$ | async }}</h4>
  <p>{{ address.city }} {{ address.zipCode }}</p>
  <p>{{ address.street }}</p>
  <p>{{ address.phone }}</p>
</div>

Doskonale wiemy, że jeżeli na widoku użyjemy w różnych miejscach kilka razy async pipe dla tego samego observabla, to będziemy mieli kilka subskrypcji (możemy to zaobserwować m.in. w konsoli), co niestety obniża wydajność naszej aplikacji.

Wyzwanie:

Co by było, gdybyśmy potrzebowali tego samego strumienia użyć w pięciu albo dziesięciu miejscach ?! 🙂

<p>Conctact us: {{ (address$ | async).phone }} or email!</p>

<div *ngIf="address$ | async as address" class="company-address">
  <h3>Address</h3>
  <h4>{{ company$ | async }}</h4>
  <p>{{ address.city }} {{ address.zipCode }}</p>
  <p>{{ address.street }}</p>
  <p>{{ address.phone }}</p>
</div>

terminal async - Dyrektywa *ngIf oraz operator shareReplay, czyli jak radzić sobie z wielokrotnym wykorzystaniem observabla w templatce

Jak widać na załączonym kodzie powyżej, address został pobrany dwukrotnie z uwagi na użycie dwa razy async pipe. Nie jest to dobra praktyka.

Rozwiązanie 1:

Pomocna może być tutaj dyrektywa strukturalna *ngIf. Można ją wykorzystać np. do użycia observabli z async pipe w kilku miejscach jednocześnie w wygodny sposób.

<ng-container *ngIf="address$ | async as address">
  <p>Conctact us: {{ address.phone }} or email!</p>
  
  <div class="company-address">
    <h3>Address</h3>
    <h4>{{ company$ | async }}</h4>
    <p>{{ address.city }} {{ address.zipCode }}</p>
    <p>{{ address.street }}</p>
    <p>{{ address.phone }}</p>
  </div>
</ng-container>

Zaletą tego rozwiązania jest poprawienie jakości kodu, oraz jego wydajności.

Rozwiązanie 2:

Innym rozwiązaniem, które może nam pomóc rozwiązać powyższe wyzwanie, jest skorzystanie z jednego z operatorów RxJs, jakim jest shareReplay. Dzięki cache-owaniu, zapamiętuje on ostatnio przychodzące wiadomości, przez co nie powiela ponownego wysłania np. żądań HTTP.

Aby zapewnić uniknięcie podwójnej subskrypcji, wystarczy powyższy operator zastosować w następujący sposób. Wyświetli nam w konsoli tylko jedną subskrypcję do naszego adresu, mimo użycia kilku async pipe w widoku HTML.

  ngOnInit(): void {
    this.address$ = of(this.addressApi).pipe(
       tap(address => console.log('address', address)),
       shareReplay()
    );
  }

Podsumowanie:

Przedstawiłem tutaj dwa sposoby na radzenie sobie z wielokrotnym wykorzystaniem strumieni. Oczywiście, istnieją też inne możliwości rozwiązania tego samego problemu. 🙂

Jeżeli potrzebujesz, już teraz wykorzystaj kod i dołącz do swojego projektu, nie robiąc niepotrzebnych async pipe w wielu miejscach i popraw wydajność swojej aplikacji. 😊

Oceń ten post
Marcin Bogucki
Autor: Marcin Bogucki
Front-end Developer at Sii - Technologie (HTML, CSS, JavaSript, TypeScript, Angular, React). W wolnym czasie gram w planszówki, lubię gotować i morsować :)

Imię i nazwisko (wymagane)

Adres email (wymagane)

Temat

Treść wiadomości

Zostaw komentarz