私のアプリケーションには、EventService
を使用して通信するコンポーネントがいくつかあります。
@Injectable()
export class EventService {
public myEvent: EventEmitter<any> = new EventEmitter();
constructor() {}
}
このサービスは、ボタンがクリックされたときにイベントを発行するEmitterComponent
に注入されます
@Component({
selector: 'emitter',
template: `<button (click)="onClick()">Click me</button>`,
})
export class EmitterComponent {
constructor(private eventService:EventService) {}
onClick() {
this.eventService.myEvent.emit();
}
}
そして、イベントにサブスクライブするReceiverComponent
で、受信したイベントごとにカウンターをインクリメントします
@Component({
selector: 'receiver',
template: `Count: {{count}}`,
})
export class ReceiverComponent {
public count = 0;
constructor(private eventService:EventService) {
this.eventService.myEvent.subscribe(() => this.count++;);
}
}
アプリケーションには複数のビューがあります(この例では2つだけです):PageA
とPageB
。 EmitterComponent
とReceiverComponent
はPageA
にあります。 PageB
に移動してPageA
に戻るたびに、新しいReceiverComponent
が作成され、EmitterComponent
のボタンをクリックすると、イベントコールバック関数of ReceiverComponent
が数回実行されます。
これを避けるため、ReceiverComponent
のmyEvent
からngOnDestroy
の購読を解除します
ngOnDestroy() {
this.eventService.myEvent.unsubscribe();
}
しかし、これにより次の例外が発生します
EXCEPTION: Error during instantiation of ReceiverComponent!.
ORIGINAL EXCEPTION: Error: Cannot subscribe to a disposed Subject
どうすればそれを回避できますか?正しく退会する方法は?
理解を深めるために、これを作成しました plunker コンソールでエラーとコメントを確認できます。
.subscribe()
からサブスクリプションを取得します。 unsubscribe()
メソッドを使用して、サブスクリプションをキャンセルします。
@Component({
selector: 'receiver',
template: `Count: {{count}}`,
})
export class ReceiverComponent {
public count = 0;
private subscription;
constructor(private eventService:EventService) {
this.subscription = this.eventService.myEvent.subscribe(() => this.count++;);
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
こちらもご覧ください
angular 2 で複数のサブスクライバーの購読を解除する方法
以下に説明するように、サブスクリプションをキャンセルする必要があると思います。
export class ReceiverComponent {
public count = 0;
private id;
constructor(private eventService:EventService) {
this.id = Date.now();
console.log("ReceiverComponent constructor " + this.id);
this.subscription = this.eventService.myEvent.subscribe(() => {
console.log("count " + this.count + " (id ReceiverComponent instance: " + this.id + ")");
this.count++;
});
}
ngOnDestroy() {
console.log("onDestroy of ReceiverComponent " + this.id)
//this cause "Cannot subscribe to a disposed Subject."
//this.eventService.myEvent.unsubscribe();
this.subscription.unsubscribe();
}
}
実際、EventEmitter
sは共有オブザーバブル、つまりホットオブザーバブルです。興味のあるリンクは次のとおりです。 https://github.com/Reactive-Extensions/RxJS/blob/master/doc/gettingstarted/creating.md 。
お役に立てばと思います、ティエリー