is there an equivalent of async pipe that you can use inside a component?

前端 未结 4 938
离开以前
离开以前 2021-02-13 03:52

Does there exist something equivalent to the async pipe that I could use inside a component like this

   @Component({
      selector: \'my-component         


        
4条回答
  •  深忆病人
    2021-02-13 04:43

    No there's not. You need to manually subscribe and manually unsubscribe to avoid memory leaks.

    For a simple subscription you may be tempted to do :

    @Component({
      selector: 'my-component',
    })
    export class myComponent implements OnInit, OnDestroy {
      public myObservable$: Observable;
      private myObservableSub: Subscription;
    
      ngOnInit() {
        this.myObservableSub = this
          .myObservable$
          .subscribe(_ => {
            // do something
          });
      }
    
      ngOnDestroy() {
        this.myObservableSub();
      }
    }
    

    But what if you have many subscribe ? Should you do something like :

    @Component({
      selector: 'my-component',
    })
    export class myComponent implements OnInit, OnDestroy {
      public myObservable1$: Observable;
      private myObservableSub1: Subscription;
    
      public myObservable2$: Observable;
      private myObservableSub2: Subscription;
    
      public myObservable3$: Observable;
      private myObservableSub3: Subscription;
    
      ngOnInit() {
        this.myObservableSub1 = this
          .myObservable1$
          .subscribe(_ => {
            // do something
          });
    
        this.myObservableSub2 = this
          .myObservable2$
          .subscribe(_ => {
            // do something
          });
    
        this.myObservableSub3 = this
          .myObservable3$
          .subscribe(_ => {
            // do something
          });
      }
    
      ngOnDestroy() {
        this.myObservableSub1();
        this.myObservableSub2();
        this.myObservableSub3();
      }
    }
    

    **THE ANSWER IS NO**

    Upadted reply (16/11/20)

    In the original answer (see after this edit), I do avise to use take until but this forces you to create a subject and trigger an event into it when the component is destroyed. While the idea behind this is good, it's quite a lot of boilerplate to put in all the components where we subscribe to a stream.

    Instead of this, we can create a custom operator that we can call takeUntilDestroyed and do something like this:

    @Component({
      selector: 'my-component',
    })
    export class myComponent implements OnInit, OnDestroy {
      public myObservable1$: Observable; // define your observable
    
      public myObservable2$: Observable; // define your observable
    
      public myObservable3$: Observable; // define your observable
    
      ngOnInit() {
        this
          .myObservable1$
          .pipe(takeUntilDestroyed(this))
          .subscribe(_ => {
            // do something
          });
    
        this.myObservableSub2 = this
          .myObservable2$
          .pipe(takeUntilDestroyed(this))
          .subscribe(_ => {
            // do something
          });
    
        this.myObservableSub3 = this
          .myObservable3$
          .pipe(takeUntilDestroyed(this))
          .subscribe(_ => {
            // do something
          });
      }
    
      ngOnDestroy() {}
    }
    

    The implementation of this custom operator can be found here: https://github.com/cloudnc/ngx-sub-form/blob/1115b21a007f72c54b521b3bed7c40051302145a/projects/ngx-sub-form/src/lib/shared/ngx-sub-form-utils.ts#L145-L148

    Original reply

    You should rather do the following :

    @Component({
      selector: 'my-component',
    })
    export class myComponent implements OnInit, OnDestroy {
      private componentDestroyed$ = new Subject();
    
      public myObservable1$: Observable;
      public myObservable2$: Observable;
      public myObservable3$: Observable;
    
      ngOnInit() {
        this
          .myObservable1$
          .takeUntil(componentDestroyed$)
          .subscribe(_ => {
            // do something
          });
    
        this
          .myObservable2$
          .takeUntil(componentDestroyed$)
          .subscribe(_ => {
            // do something
          });
    
        this
          .myObservable3$
          .takeUntil(componentDestroyed$)
          .subscribe(_ => {
            // do something
          });
      }
    
      ngOnDestroy() {
        this.componentDestroyed$.next();
        this.componentDestroyed$.complete();
      }
    }
    

    If you want to know more about that, here's an excellent article from Ben Lesh : https://medium.com/@benlesh/rxjs-dont-unsubscribe-6753ed4fda87

    EDIT :
    Thanks to @olsn, I edited my answer and added the line with the next because indeed a complete doesn't stop the others streams.

    I created a small Plunkr to demo that behaviour : https://plnkr.co/edit/dcueDqUgpqgYimxEAGUn?p=preview

提交回复
热议问题