typescript - Angular prenumerera/avprenumerera bästa praxis


Jag funderar för närvarande på Angular-prenumeration och avprenumeration. Det finns mycket material om ämnet, så jag är lite vilsen i allt detta.

När ska jag avsluta prenumerationen? Vad händer om jag aldrig avslutar den? Jag stöter aldrig på några fel från återstående prenumeration.

Finns det ett sätt att automatiskt avsluta prenumerationer på allt i en komponent/app, så att jag inte behöver deklarera 1 egenskap per prenumeration? Detta kan vara väldigt irriterande :

@Component({
  selector: 'subscriptionTest',
  template: `...`,
})
export class SubTestComponent {
  first;
  second;
  third;

  constructor(private remote: RemoteService){}

  ngOnInit() {
    this.first = remote.getSomeData().subscribe(data => // do something);
    this.second = Observable.interval(500).subscribe(event => // do something);
    this.third = remote.getSomeOtherData().subscribe(data => // do something);

  }

  ngOnDestroy() {
    this.first.unsubscribe();
    this.second.unsubscribe();
    this.third.unsubscribe();
  }

}

Svar #1

Om du inte vill upprepa dig själv, använd en superklass:

/**
*  Unsubscribe from any Observable using takeUntil and this.destroy$
*      someObservable.pipe( // lettable operators in rxjs ^5.5.0
*          ...
*          takeUntil(destroy$)
*      )
*      .subscribe(....
**/
export class Destroyer implements OnDestroy {
    destroy$: Subject<boolean> = new Subject<boolean>();

    ngOnDestroy() {
        // Unsubscribe from whatever used takeUntil(destroy$)
        this.destroy$.next(true);
        // Now let's also unsubscribe from the subject itself:
        this.destroy$.unsubscribe();
    }
}

Använd det överallt:

export class SomeComponent extends Destroyer{

   constructor(private remote: RemoteService){
       super();
   }

   ngOnInit() {
        remote.getSomeData()
              .pipe(takeUntil(this.destroy$)) 
              //.takeUntil(this.destroy$) // before rxjs ^5.5.0
              .subscribe(data => {/* do something*/});

        Observable.interval(500)
              .pipe(takeUntil(this.destroy$))
              //.takeUntil(this.destroy$) // before rxjs ^5.5.0
              .subscribe(data => {/* do something*/});
      }
   }

   // optional. You don't need ngOnDestroy everywhere.
   ngOnDestroy(): void {

       // Let Destroyer trigger unsubscribe
       super.ngOnDestroy();

       // ...SomeComponent other cleanup.
   }


}

Svar #2

Operatorn takeUntil är ett enkelt sätt att "automatiskt" avregistrera sig från vilken prenumeration som helst, exempel:

@Component({...})
export class AppComponent implements OnInit, OnDestroy {
  destroy$: Subject<boolean> = new Subject<boolean>();

  constructor(private apollo: Apollo) {
  }

  ngOnInit() {
    this.apollo.watchQuery({
        query: gql`
        query getAllPosts {
          allPosts {
            title
            description
            publishedAt
          }
        }
      `
      })
      .takeUntil(this.destroy$)
      .subscribe(({data}) => {
        console.log(data);
      });
      remote.getSomeData().subscribe(data => // do something);
      Observable.interval(500).subscribe(event => // do something);
      remote.getSomeOtherData().subscribe(data => // do something);
  }

  onStartInterval() {
    Observable
      .interval(250)
      .takeUntil(this.destroy$)
      .subscribe(val => {
        console.log('Current value:', val);
      });
  }

  ngOnDestroy() {
    this.destroy$.next(true);
    // Now let's also unsubscribe from the subject itself:
    this.destroy$.unsubscribe();
  }
}

Du behöver inte deklarera varje prenumeration, bara lägga till .takeUntil(this.destroy$)-operatorn på varje av dem

Källa : https://alligator.io/angular/takeuntil-rxjs-unsubscribe/

Ett fantastiskt inlägg om prenumerationer: Angular/RxJs När bör jag avprenumerera från `Subscription`

Relaterade artiklar