Dans mon application, j'ai quelques composants qui communiquent au moyen de EventService
.
@Injectable()
export class EventService {
public myEvent: EventEmitter<any> = new EventEmitter();
constructor() {}
}
Ce service est injecté dans un EmitterComponent
qui émet l'événement quand un bouton est cliqué
@Component({
selector: 'emitter',
template: `<button (click)="onClick()">Click me</button>`,
})
export class EmitterComponent {
constructor(private eventService:EventService) {}
onClick() {
this.eventService.myEvent.emit();
}
}
et dans un ReceiverComponent
qui souscrit à l'événement et pour chaque événement reçu incrémente un compteur
@Component({
selector: 'receiver',
template: `Count: {{count}}`,
})
export class ReceiverComponent {
public count = 0;
constructor(private eventService:EventService) {
this.eventService.myEvent.subscribe(() => this.count++;);
}
}
L'application a plusieurs vues (dans cet exemple seulement deux): PageA
et PageB
. EmitterComponent
et ReceiverComponent
sont dans PageA
. Chaque fois que je vais dans PageB
et que je reviens dans PageA
, un nouveau ReceiverComponent
est créé et lorsque je clique sur le bouton dans EmitterComponent
, la fonction de rappel d'événement de ReceiverComponent
est exécuté plusieurs fois.
Pour éviter cela, je me désinscris ReceiverComponent
de myEvent
dans ngOnDestroy
ngOnDestroy() {
this.eventService.myEvent.unsubscribe();
}
mais cela provoque l'exception suivante
EXCEPTION: Error during instantiation of ReceiverComponent!.
ORIGINAL EXCEPTION: Error: Cannot subscribe to a disposed Subject
Comment puis-je éviter cela? Comment se désinscrire correctement?
Pour une meilleure compréhension, j'ai créé ce plunker où vous pouvez voir l'erreur et quelques commentaires dans la console.
Vous obtenez un abonnement auprès de .subscribe()
. Utilisez sa méthode unsubscribe()
pour annuler l'abonnement.
@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();
}
}
Voir également
Je pense que vous devez annuler l'abonnement, comme décrit ci-dessous:
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();
}
}
En fait, EventEmitter
s sont des observables partagés, c'est-à-dire des observables à chaud. Voici un lien qui pourrait vous intéresser: https://github.com/Reactive-Extensions/RxJS/blob/master/doc/gettingstarted/creating.md .
J'espère que cela vous aide, Thierry