example - unsubscribe observable angular 4
Angular2, anular la suscripciĆ³n del evento en ngOnDestroy (2)
Esta pregunta ya tiene una respuesta aquí:
- Cómo cancelar una suscripción en Angular2 8 respuestas
En mi aplicación tengo algunos componentes que se comunican mediante EventService
.
@Injectable()
export class EventService {
public myEvent: EventEmitter<any> = new EventEmitter();
constructor() {}
}
Este servicio se inyecta en un EmitterComponent
que emite el evento cuando se hace clic en un botón
@Component({
selector: ''emitter'',
template: `<button (click)="onClick()">Click me</button>`,
})
export class EmitterComponent {
constructor(private eventService:EventService) {}
onClick() {
this.eventService.myEvent.emit();
}
}
y en un ReceiverComponent
que se suscribe al evento y por cada evento recibido aumenta un contador
@Component({
selector: ''receiver'',
template: `Count: {{count}}`,
})
export class ReceiverComponent {
public count = 0;
constructor(private eventService:EventService) {
this.eventService.myEvent.subscribe(() => this.count++;);
}
}
La aplicación tiene múltiples vistas (en este ejemplo solo dos): PageA
y PageB
. EmitterComponent
y ReceiverComponent
están en PageA
. Cada vez que voy a PageB
y vuelvo a PageA
, se PageA
un nuevo ReceiverComponent
y cuando hago clic en el botón en EmitterComponent
, la función de devolución de llamada de evento de ReceiverComponent
se ejecuta varias veces.
Para evitar esto, doy de baja ReceiverComponent
de myEvent
en ngOnDestroy
ngOnDestroy() {
this.eventService.myEvent.unsubscribe();
}
pero esto provoca la siguiente excepción
EXCEPTION: Error during instantiation of ReceiverComponent!.
ORIGINAL EXCEPTION: Error: Cannot subscribe to a disposed Subject
¿Cómo puedo evitar eso? ¿Cómo darse de baja correctamente?
Para una mejor comprensión, he creado este plunker donde puede ver el error y algunos comentarios en la consola.
Creo que deberías cancelar la suscripción, como se describe a continuación:
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();
}
}
De hecho, los EventEmitter
son observables compartidos, es decir, observables en caliente. Aquí hay un enlace que podría interesarle: https://github.com/Reactive-Extensions/RxJS/blob/master/doc/gettingstarted/creating.md .
Espero te ayude, Thierry
.subscribe()
una suscripción de .subscribe()
. Use su método para unsubscribe()
para cancelar la suscripción.
@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();
}
}
Ver también