问题
In my application I have some components that communicate by means of EventService
.
@Injectable()
export class EventService {
public myEvent: EventEmitter<any> = new EventEmitter();
constructor() {}
}
This service is injected in a EmitterComponent
that emits the event when a button is clicked
@Component({
selector: 'emitter',
template: `<button (click)="onClick()">Click me</button>`,
})
export class EmitterComponent {
constructor(private eventService:EventService) {}
onClick() {
this.eventService.myEvent.emit();
}
}
and in a ReceiverComponent
that subscribes to the event and for each event received increments a counter
@Component({
selector: 'receiver',
template: `Count: {{count}}`,
})
export class ReceiverComponent {
public count = 0;
constructor(private eventService:EventService) {
this.eventService.myEvent.subscribe(() => this.count++;);
}
}
The application has multiple views (in this example just two): PageA
and PageB
. EmitterComponent
and ReceiverComponent
are in PageA
. Every time I go to PageB
and come back to PageA
, a new ReceiverComponent
is created and when I click the button in EmitterComponent
, the event callback function of ReceiverComponent
is executed several times.
To avoid this I unsubscribe ReceiverComponent
from myEvent
in ngOnDestroy
ngOnDestroy() {
this.eventService.myEvent.unsubscribe();
}
but this causes the following Exception
EXCEPTION: Error during instantiation of ReceiverComponent!.
ORIGINAL EXCEPTION: Error: Cannot subscribe to a disposed Subject
How can I avoid that? How to unsubscribe correctly?
For a better understanding I've created this plunker where you can see the error and some comments in the console.
回答1:
You get a subscription from .subscribe()
. Use its unsubscribe()
method to cancel the subscription.
@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();
}
}
See also
how to unsubscribe several subscriber in angular 2
timer.unsubscribe is not a function Angular2
回答2:
I think your should cancel the subscription, as described below:
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();
}
}
In fact, EventEmitter
s are shared observables, i.e. hot observables. Here is a link that could interest you: https://github.com/Reactive-Extensions/RxJS/blob/master/doc/gettingstarted/creating.md.
Hope it helps you, Thierry
来源:https://stackoverflow.com/questions/34926628/angular2-unsubsribe-from-event-in-ngondestroy