简体   繁体   English

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

[英]Angular 2 - Does subscribing to FormControl's valueChanges need an unsubscribe?

Below is a simple example of what I am asking about:以下是我要问的一个简单示例:

class AppComponent {

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

  constructor(){

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

I have 2 questions:我有两个问题:

1) Do I have to eventually unsubscribe from this? 1)我最终必须取消订阅吗? 2) Most importantly, whatever the answer is to #1, WHY is that the answer? 2) 最重要的是,无论#1 的答案是什么,为什么是这个答案?

Any insight would be appreciated任何见解将不胜感激

Thanks谢谢

UPDATE OCT 2020 2020 年 10 月更新

This question gets a lot of SEO traffic and whilst my answer is still technically correct, I strongly advise you to read this .这个问题获得了大量的 SEO 流量,虽然我的回答在技术上仍然是正确的,但我强烈建议您阅读此内容


  1. Yes, you do.是的你是。 Note that you do not need to unsubscribe from http calls because they auto-complete themselves.请注意,您不需要取消订阅 http 调用,因为它们会自动完成。

  2. You must unsubscribe to prevent memory leaks and to avoid unexpected side-effects in your application.您必须取消订阅以防止内存泄漏并避免应用程序中出现意外的副作用。

For example, when a component is destroyed, the subscription will remain if you don't unsubscribe from it.例如,当一个组件被销毁时,如果您不取消订阅,订阅将保留。 The next time the user navigates back to that page and the component gets loaded again, it will create another subscription to valueChanges - now you have 2 active subscriptions processing data simultaneously and that will lead to unexpected behavior in your app.下次用户导航回该页面并再次加载组件时,它将创建另一个对valueChanges订阅 - 现在您有 2 个活动订阅同时处理数据,这将导致您的应用程序出现意外行为。

There is a relatively easy way to setup auto-unsubscribing.有一种相对简单的方法来设置自动取消订阅。

The RxJS way is to use takeUntil - it basically lets you set up a subscriber which keeps listening UNTIL you tell it not to :) RxJS 的方法是使用takeUntil - 它基本上允许您设置一个订阅者,该订阅者一直监听直到您告诉它不要:)

First we need a destroy subject in our component:首先,我们需要在组件中创建一个销毁主题:

  private destroy$ = new Subject();

Then tell it to emit a value when our component is destroyed:然后告诉它在我们的组件被销毁时发出一个值:

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

Now setup your subscribes to use it:现在设置您的订阅以使用它:

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

All the subscribes setup like this will then auto-unsubscribe when they receive the destroy notification.所有像这样的订阅设置将在收到销毁通知时自动取消订阅。

This is especially useful if, for example, you have an ngFor that is dynamically adding controls, and each control added has an valueChanges subscription (eg. an array of controls).例如,如果您有一个动态添加控件的 ngFor,并且添加的每个控件都有一个 valueChanges 订阅(例如,一个控件数组),这将特别有用。 In such a scenario you don't need to loop through the array in ngOnDestroy and unsubscribe one-by-one.在这种情况下,您不需要遍历 ngOnDestroy 中的数组并逐一取消订阅。 Just use takeUntil :)只需使用 takeUntil :)

I recommend reading Ben Lesh's article (RxJS lead engineer at Google) for a great overview of takeUntil, including pros/cons.我建议阅读Ben Lesh 的文章(Google 的 RxJS 首席工程师),以全面了解 takeUntil,包括优点/缺点。

  1. Yes.是的。
  2. For thing whatever subscribe, you need to unsubscribe to prevent memory leak.无论订阅什么,您都需要取消订阅以防止内存泄漏。 There are a few way to unsubscribe.有几种方法可以取消订阅。 a.一种。 "auto unsubscribe after N time" - add .take(numberOfTimes) will unsubscribe after the N time you specified. “N 次后自动取消订阅” - 添加.take(numberOfTimes)将在您指定的 N 次后取消订阅。 For example:例如:

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

    b.Unsubscribe during component lifecycle manually, normally during ngOnDestroy()在组件生命周期中手动取消订阅,通常在ngOnDestroy()期间

I highly recommend the rxjs extension https://github.com/ngneat/until-destroy .我强烈推荐 rxjs 扩展https://github.com/ngneat/until-destroy It will help you write less code.它将帮助您编写更少的代码。

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

Yes we need to unsubscribe valueChanges subscription to prevent memory leaks.是的,我们需要取消订阅valueChanges以防止 memory 泄漏。 You can check simply check demo here您可以在这里查看简单的查看演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM