javascript - Observable vs Subject și asObservable


Învăț RxJs, caut confirmare sau corectare asupra presupunerii mele.

Încerc să creez un observable public doar pentru citire într-un serviciu pe care să pot folosi .next() în diverse locuri din clasa mea de serviciu. Mă întreb dacă aceasta este modalitatea corectă de a o face:

private myObservable = new Subject<T>();
public myObservable$: Observable<T> = this.myObservable.asObservable();
  • Utilizatorul se poate abona la myObservable$
  • Pot să folosescmyObservable.next(...);

Funcționează perfect, dar am suficientă experiență pentru a ști că s-ar putea doar să fiu un idiot fără să-mi dau seama (RxJS este imens). Este acesta un model corect și obiectul corect pentru cazul de utilizare menționat?

Răspuns #1

Ceea ce faci este corect. Există totuși o notație puțin mai scurtă. Deoarece Subject este deja un Observable (moștenește clasa Observable), poți lăsa verificarea tipului pe seama TypeScript:

private myObservable = new Subject<T>();
public myObservable$: Observable<T> = this.myObservable;

Orice consumator al serviciului tău se poate abona la myObservable$, dar nu va putea să apeleze myObservable$.next() deoarece TypeScript nu îți va permite să faci asta (clasa Observable nu are nicio metodă next()).

Aceasta este, de fapt, modalitatea recomandată de a face acest lucru, iar RxJS intern nu folosește niciodată asObservable. Pentru o discuție mai detaliată, vezi:

  • https://github.com/ReactiveX/rxjs/pull/2408

  • https://github.com/ReactiveX/rxjs/issues/2391

Vezi o întrebare foarte similară: Ar trebui ca subiectele rxjs să fie publice în clasă?

Răspuns #2

În proiect folosim acest tip de Observables, acesta oferă o încapsulare corespunzătoare pentru observable-ul tău privat, dar tot poți apela next() folosind o metodă publică.

      private sourceName = new Subject<T>();
      name = this.sourceProductName.asObservable();

      sendName(item: T) {
        this.sourceName.next(item);
      }