Angular 2 - FormGroup ValueChanges取消订阅

Dav*_*wys 11 rxjs angular2-forms angular

我有一个带有ValueChanges事件的FormGroup,当用户从组件的路径移动到另一个组件然后它们返回到组件时,该事件不会从内存中释放.

这意味着如果用户导航远离组件然后返回组件5次,则onFormChange方法将触发5次,但这些调用中只有1次针对当前组件.

我认为问题是我需要取消订阅NgDestroy事件中的valueChanges事件,但valueChanges事件中没有可用的取消订阅方法.

我确信我必须取消订阅或释放内存,但我不确定是什么.

import * as _ from 'lodash';
import {Observable} from 'rxjs/Rx';

import {Component, Input, Output, EventEmitter, OnInit, OnDestroy} from '@angular/core';
import {FormGroup} from '@angular/forms';

import {formConfig} from './toolbar.form-config';
import {JobToolbarVm} from '../view-model/job-toolbar.vm';
import {BroadcastService} from '../../../services/broadcast/broadcast.service';

@Component({
    selector: 'wk-job-toolbar',
    template: require('./toolbar.html'),
})
export class JobToolbarComponent implements OnInit, OnDestroy {

  protected form: FormGroup;

  @Input()
  toolbar: JobToolbarVm;

  @Output()
  toolbarChanged = new EventEmitter<JobToolbarVm>();

  @Output()
  refresh = new EventEmitter<string>();

  constructor(private broadcast: BroadcastService) {
  }

  ngOnInit() {

    this.form = formConfig;
    this.form.setValue(this.toolbar, {onlySelf: true});

    // This ALWAYS RUNS when the form loads, ie. on the job route
    console.log('FORM VALUE');
    console.log(JSON.stringify(this.form.value, null, 2));

    this.form.valueChanges
      .debounceTime(2000)
      .subscribe(
        this.onFormChange.bind(this)
      );
  }

  ngOnDestroy() {
    //this.form.valueChanges.unsubscribe();
    //this.onChanges.unsubscribe();
    //this.toolbarChanged.unsubscribe();
    //this.form = null;
  }

  onFormChange(data: any) {
    // This runs whenever I go to a different route and then come back to this route
    // There is also a memory leak, because this method fires multiple times based on how
    // often I navigate away and come back to this route.
    // e.g. Navigate away and then back 5 times, then I see this log statement 5 times 
    console.log('FORM VALUE2 - THIS KEEPS FIRING FOR EACH INSTANCE OF MY COMPOMENT');
    console.log(JSON.stringify(this.form.value, null, 2));

    JobToolbarVm.fromJsonIntoInstance(data, this.toolbar);

    this.onChanges('data-changed');
  }

  onChanges($event: any) {
    console.log('onChanges: ' + $event);
    // console.log(this.toolbar);

    // Send the toolbar object back out to the parent
    this.toolbarChanged.emit(this.toolbar);

    // Broadcast an event that will be listened to by the list component so that it knows when to refresh the list
    this.broadcast.broadcast('job-admin-toolbar-changed', this.toolbar);
  }
}
Run Code Online (Sandbox Code Playgroud)

Gün*_*uer 14

subscribe()调用返回a Subscription,这是您用来取消订阅的内容:

class JobToolbarComponent

  private subscr:Subscription;

  ngOnInit() {
    ...
    this.subscr = this.form.valueChanges ...
    ...
  }

  ngOnDestroy() {
    this.subscr.unsubscribe();
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 当组件中创建了`this.form`后,哪个事件可以在组件被销毁后触发`ValueChange`?我无法想象我需要取消订阅自己创建的表单的情况。如果“unsubscribe”可以在“debounceTime”之后停止流程(请参见上面的示例),也会很有趣。顺便说一句,你的答案是正确的 - 我的评论更多的是关于“我们必须取消订阅吗?”。 (3认同)
  • 你好!非常感谢您的回答。我不断地阅读它们。订阅了您的github。但是您能否解释一下,如果组件和表单被自己破坏了,为什么我们需要取消订阅,垃圾回收器不应该从内存中删除订阅吗? (2认同)
  • 谢谢:-)通常,如果您必须订阅,最好先取消订阅。也可能是垃圾回收没有立即处理组件实例,然后它仍然可能收到一些事件,直到最终消失。当组件不再活动时,订阅回调可能会导致错误,或者可能会导致昂贵的操作(网络请求),而当组件被处置时,这些操作就不再需要。 (2认同)