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.
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
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With