2017-05-08 18 views
3

ユーザーがコンポーネントのルートから別のコンポーネントに移動してからコンポーネントに戻るとき、メモリから解放されないValueChangesイベントを持つFormGroupがあります。角2 - FormGroup ValueChanges購読中止

これは、ユーザーがコンポーネントからナビゲートしてコンポーネントに5回戻ると、onFormChangeメソッドが5回発生しますが、これらの呼び出しのうち1つだけが現在のコンポーネントであることを意味します。

問題は、NgDestroyイベントのvalueChangesイベントの登録を解除する必要がありましたが、valueChangesイベントで利用可能なunsubscribeメソッドがないことがわかりました。

私は何かのためにメモリを退会または解放しなければならないと確信していますが、私は何がわかりません。

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

答えて

2

subscribe()呼び出しがSubscriptionを返し、これはあなたが退会するために使用するものです。

class JobToolbarComponent 

    private subscr:Subscription; 

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

    ngOnDestroy() { 
    this.subscr.unsubscribe(); 
    } 
} 
+0

おかげでかなりクールです - :それは下に記載されてどのように使用します、それは私のために働いた –

0

私は実際にあなたが自動配信停止に使用することができます

export function AutoUnsubscribe(exclude = []) { 

    return function (constructor) { 

     const original = constructor.prototype.ngOnDestroy; 

     constructor.prototype.ngOnDestroy = function() { 
      for (let prop in this) { 
       const property = this[prop]; 
       if (!exclude.includes(prop)) { 
        if (property && (typeof property.unsubscribe === "function")) { 
         property.unsubscribe(); 
        } 
       } 
      } 
      original && typeof original === 'function' && original.apply(this, arguments); 
     }; 
    } 

} 

この次の関数を作成しましたすべてのウォッチャーがあなたをパブリックプロパティに格納しなければならないので、この関数はそれを傍受し、そのサブスクライブを解除することができます。私からアイデアをとっているのです。このブログを読んでくださいデコレータを使用する方法の詳細について

@AutoUnsubscribe() 
@Component({ 
    selector: 'account-login', 
    templateUrl: './login.component.html', 
    styleUrls: ['./login.component.scss'] 
}) 
export class LoginComponent implements OnInit { 


    public submitWatcher: Subscription; 

    submit() { 
     this.submitWatcher = this.authService.login(this.loginForm.getRawValue()) 
      .subscribe(res => { 
       if (this.returnUrl) { 
        this.router.navigate([this.returnUrl]); 
       } 
       else { 
        this.router.navigate(['/special']); 
       } 
      }, (error) => { 
       alert(JSON.stringify(error.data)); 
      }); 
    } 

} 

、それは

Blog

関連する問題