When to Unsubscribe in Angular

作者:Netanel Basal 发表日期:2017-12-10 15:17:21 更新日期:2017-12-10 15:17:21 分类:猿文色

摘要

转载自: https://netbasal.com/when-to-unsubscribe-in-angular-d61c6b21bad3

正文

As you probably know when you subscribe to an observable or event in JavaScript, you usually need to unsubscribe at a certain point to release memory in the system. Otherwise, you will have a memory leak.

Let’s see the most common cases that you will need to unsubscribe inside the ngOnDestroy lifecycle hook.

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();
  }

}

This also applies to any 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
  }

}

According to the official documentation, Angular should unsubscribe for you, but apparently, there is a 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

When you have an infinite sequence, you should unsubscribe (unless you have a special case), for example when using the interval() or the fromEvent() 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();
  }

}

ngrx/store and redux-angular select method returns an observable. Therefore they have to be cleaned.