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, EventEmitters 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