Angular 2 - 订阅FormControl的valueChanges是否需要取消订阅?

时间:2016-12-28 14:30:02

标签: angular rxjs

以下是我所询问的一个简单示例:

class AppComponent {

  someInput: FormControl = new FormControl('');
  private subscription: Subscription;

  constructor(){

    this.subscription = this.someInput.valueChanges
        .subscribe(() => console.log("testing"));
  }
}

我有两个问题:

1)我是否必须最终取消订阅? 2)最重要的是,无论答案是什么#1,为什么答案都是答案?

任何见解都将受到赞赏!

谢谢!

3 个答案:

答案 0 :(得分:15)

  1. 是的,你这样做。请注意,您不需要unsubscribe from http calls,因为它们会自动完成。

  2. 您必须取消订阅以防止内存泄漏并避免应用程序中出现意外的副作用。

  3. 例如,当组件被销毁时,如果您不取消订阅,则订阅将保留。下次用户导航回该页面并再次加载组件时,它将创建另一个valueChanges订阅 - 现在您有2个活动订阅同时处理数据,这将导致您的应用程序出现意外行为。< / p>

    有一种相对简单的方法可以设置自动取消订阅。

    RxJS方式是使用takeUntil - 它基本上可以让你设置一个持续收听的用户 UNTIL你告诉它不要:)

    首先,我们需要在组件中使用destroy主题:

      private destroy$ = new Subject();
    

    然后告诉它在我们的组件被销毁时发出一个值:

      ngOnDestroy(){
        this.destroy$.next();
      }
    

    现在设置您的订阅以使用它:

    this.someInput.valueChanges
      .debounceTime(1000)
      .distinctUntilChanged()
      .takeUntil(this.destroy$)
      .subscribe (newValue => {
    

    所有这样设置的订阅将在收到销毁通知后自动取消订阅。

    例如,如果你有一个动态添加控件的ngFor,并且添加的每个控件都有一个valueChanges订阅(例如一个控件数组),那么这个特别有用。在这种情况下,您无需在ngOnDestroy中循环遍历数组并逐个取消订阅。只需使用takeUntil:)

    我建议您阅读Ben Lesh's article(Google的RxJS首席工程师),了解takeUntil的概况,包括优缺点。

答案 1 :(得分:2)

  1. 对于任何订阅的东西,您需要取消订阅以防止内存泄漏。有几种方法可以取消订阅。  一个。 “N次后自动取消订阅” - 添加.take(numberOfTimes)将在您指定的N次之后取消订阅。例如:

    this.subscription = this.someInput.valueChanges
        .take(2) // unsubscribe after 2 times
        .subscribe(() => console.log("testing"));
    

    湾在组件生命周期中手动取消订阅,通常在ngOnDestroy()

  2. 期间

答案 2 :(得分:0)

我强烈推荐 rxjs 扩展 https://github.com/ngneat/until-destroy 。它将帮助您编写更少的代码。

@UntilDestroy()
@Component({})
export class InboxComponent {
  ngOnInit() {
    this.someInput.valueChanges
      .pipe(untilDestroyed(this))
      .subscribe();
  }
}