美文网首页我爱编程
Angular中之Unsubscribe

Angular中之Unsubscribe

作者: CK110 | 来源:发表于2018-02-12 10:48 被阅读434次

    需要unsubscribe的常见情况

    Forms —

    export class TestComponent {
    
      ngOnInit() {
        this.form = new FormGroup({...});
        this.valueChanges  = this.form.valueChanges.subscribe(console.log);
        this.statusChanges = this.form.statusChanges.subscribe(console.log);
      }
    
      ngOnDestroy() {
        this.valueChanges.unsubscribe();
        this.statusChanges.unsubscribe();
      }
    
    }
    

    form control中同理

    The Router —

    export class TestComponent {
      constructor(private route: ActivatedRoute, private router: Router) { }
    
      ngOnInit() {
        this.route.params.subscribe(console.log);
        this.route.queryParams.subscribe(console.log);
        this.route.fragment.subscribe(console.log);
        this.route.data.subscribe(console.log);
        this.route.url.subscribe(console.log);
        
        this.router.events.subscribe(console.log);
      }
    
      ngOnDestroy() {
        // You should unsubscribe from each observable here
      }
    
    }
    

    根据官方文档,Angular应该自动unsubscribe,但这里面有个bug

    Renderer Service —

    export class TestComponent {
    constructor(private renderer: Renderer2, 
                private element : ElementRef) { }
    
      ngOnInit() {
        this.click = this.renderer.listen(this.element.nativeElement, "click", handler);
      }
    
      ngOnDestroy() {
        this.click.unsubscribe();
      }
    
    }
    

    Infinite Observables

    export class TestComponent {
    
      constructor(private element : ElementRef) { }
    
      interval: Subscription;
      click: Subscription;
    
      ngOnInit() {
        this.interval = Observable.interval(1000).subscribe(console.log);
        this.click = Observable.fromEvent(this.element.nativeElement, 'click').subscribe(console.log);
      }
    
      ngOnDestroy() {
        this.interval.unsubscribe();
        this.click.unsubscribe();
      }
    
    }
    

    Redux Store —

    export class TestComponent {
    
      constructor(private store: Store) { }
    
      todos: Subscription;
    
      ngOnInit() {
         this.todos = this.store.select('todos').subscribe(console.log);  
      }
    
      ngOnDestroy() {
        this.todos.unsubscribe();
      }
    
    }
    

    不需要 Unsubscribe 的情况

    Async pipe —

    @Component({
      selector: 'test',
      template: `<todos [todos]="todos$ | async"></todos>`
    })
    export class TestComponent {
    
      constructor(private store: Store) { }
    
      ngOnInit() {
         this.todos$ = this.store.select('todos');
      }
    
    }
    

    当组件被销毁时,async管道自动取消订阅,以避免潜在的内存泄漏。

    @HostListener —

    export class TestDirective {
    
      @HostListener('click')
      onClick() {
        ....
      }
    }
    

    Finite Observable —

    当你有一个有限的序列,通常你不需要unsubscribe,例如当使用HTTPservice或timer observable。

    export class TestComponent {
    
      constructor(private http: Http) { }
    
      ngOnInit() {
        Observable.timer(1000).subscribe(console.log);
        this.http.get('http://api.com').subscribe(console.log);
      }
    }
    

    小建议

    不要过多的调用unsubscribe方法,RxJS: Don’t Unsubscribe

    takeUntil
    它发出源 Observable 的值,然后直到第二个 Observable (即 notifier )发出项,它便完成。

    export class TestComponent {
    
      constructor(private store: Store) { }
    
      private componetDestroyed: Subject = new Subject();
      todos: Subscription;
      posts: Subscription;
    
      ngOnInit() {
         this.todos = this.store.select('todos').takeUntil(this.componetDestroyed).subscribe(console.log); 
    
         this.todos = this.store.select('posts').takeUntil(this.componetDestroyed).subscribe(console.log); 
      }
    
      ngOnDestroy() {
        this.componetDestroyed.next(); // componetDestroyed 发出值后,todos,todos会completed
        this.componetDestroyed.unsubscribe();
      }
    
    }
    

    相关文章

      网友评论

        本文标题:Angular中之Unsubscribe

        本文链接:https://www.haomeiwen.com/subject/dxertftx.html