javascript - Dezavantajele utilizării subject-urilor ca asObservable


Bună, chiar mă întreb asupra utilizării apelului „asObserveable()” pe subject.

Din punctul meu de vedere, creează un mare overhead inutil. Prevenirea apelurilor precum „next()” sau „complete()” este, în opinia mea, inutilă.

Mă poți numi un motiv bun pentru care ar trebui să faci asta?

Doar compară aceste două

  1. Fără
export class TestService {
     public get test$(): Observable<test> {
        return this.test$.asObservable();
     }
    
      public get test2$(): Observable<test> {
        return this.test2$.asObservable();
      }
    
      public get test3$(): Observable<test3> {
        return this.test3$.asObservable();
      }
    
      public get test4$(): Observable<test4> {
        return this.test4$.asObservable();
      }
    
      private readonly _test1$ = new ReplaySubject<test1>(1);
      private readonly _test2$ = new ReplaySubject<test2>(1);
      private readonly _test3$ = new ReplaySubject<test3>(1);
      private readonly _test4$ = new ReplaySubject<test4>(1);
 }

  1. Fără
 export class TestService {  
      public readonly test1$ = new ReplaySubject<test1>(1);
      public readonly test2$ = new ReplaySubject<test2>(1);
      public readonly test3$ = new ReplaySubject<test3>(1);
      public readonly test4$ = new ReplaySubject<test4>(1);
}

Răspuns #1

Dezavantajele lui subject ca Observable

Câțiva coduri standard. Nu prea mult altceva.

În opinia mea, creează un mare surplus inutil.

Ai măsurat-o? Subiecții extind Observables, tot ce face este să creeze o copie superficială. Aș fi surprins dacă ai găsi o aplicație unde diferența este mai mare decât varianța (efectiv, nu măsurabilă).

Avantajele lui subject ca Observable

O arhitectură mai curată înseamnă că este mai ușor să găsești erori și/sau mai ușor să previi apariția erorilor de la bun început.

Încapsularea este unul dintre fundamentele unei arhitecturi curate. Deoarece încapsularea ascunde o parte din programul nostru față de alte părți, face ca fiecare parte să fie puțin mai ușor de înțeles. Prin urmare, este mai ușor de înțeles, scris, extins și întreținut.

Dacă există un bug într-un sistem bine arhitecturat, suprafața afectată este mult mai mică.

În general, beneficiile pentru acest tip de decizii tind să devină evidente în proiectele mai mari cu echipe mai mari. Dacă scrieți un proiect de hobby acasă sau creați un produs minim viabil singur sau împreună cu o echipă mică, ar putea avea sens să renunțați la supra-planificare pentru a grăbi procesul. Un astfel de proiect ar putea necesita o rescriere/restructurare odată ce crește, dar până atunci efortul suplimentar va merita.

Alternative la asObservable ale Subiectului

Dacă aveți un verificator de tip static setat relativ strict (TypeScript, Elm, PureScript, ClojureScript etc.), atunci puteți să returnați pur și simplu Subiectul ca un Observable fără a face vreo modificare la reprezentarea tipului în timpul execuției.

Obții încapsularea fără niciun cost la rulare.

Răspunsul #2

Pot oferi un motiv bun. Să presupunem că doriți să emiteți un eveniment execCompleted$ bazat pe o anumită acțiune. Iată cum este implementat

export class TestService {
 private readonly execCompleted$ = new Subject<string>();

 public async makeServerCall(userData){
   const resp = await this.http.post('...').toPromise();
   this.execCompleted$.next(resp.data.id);
   return resp;
 }

 public getUpdatedId(){
   this.execCompleted$.asObservable();
 }

}

Acum, acest serviciu este folosit de două componente -> Admin și UserInfo.

Componenta Admin poate actualiza unele informații despre utilizator folosind makeServerCall() și poate actualiza unele date ale utilizatorului. Acest eveniment trebuie capturat de UserInfoComponent astfel încât acesta să poată asculta și să actualizeze informațiile (după ce s-a efectuat o actualizare).

Prin expunerea Subject folosind getUpdatedId(), restricționați orice alt component să trimită din greșeală evenimentul next() pe execCompleted$. Acest Subject va fi declanșat doar când makeServerCall(userData) este apelat.

Acesta este doar un exemplu simplu. Există cazuri mai complexe, dar toate au aceeași intenție de bază.

Să nu se permită emiterea sau anularea evenimentelor nedorite. Doar sursa intenționată ar trebui să facă acest lucru.

Aceasta este o practică standard în programare atunci când vrei anumite restricții asupra a ceea ce poate fi extins de alții și ce nu poate. Cam ca principiul open-closed.