Angular2, отписаться от события в ngOnDestroy
В моем приложении у меня есть некоторые компоненты, которые обмениваются с помощью EventService
.
@Injectable()
export class EventService {
public myEvent: EventEmitter<any> = new EventEmitter();
constructor() {}
}
Эта услуга вводится в EmitterComponent
, которая испускает событие при нажатии кнопки
@Component({
selector: 'emitter',
template: `<button (click)="onClick()">Click me</button>`,
})
export class EmitterComponent {
constructor(private eventService:EventService) {}
onClick() {
this.eventService.myEvent.emit();
}
}
и в ReceiverComponent
, который подписывается на событие и для каждого полученного события увеличивается счетчик
@Component({
selector: 'receiver',
template: `Count: {{count}}`,
})
export class ReceiverComponent {
public count = 0;
constructor(private eventService:EventService) {
this.eventService.myEvent.subscribe(() => this.count++;);
}
}
Приложение имеет несколько видов (в этом примере всего два): PageA
и PageB
. EmitterComponent
и ReceiverComponent
находятся в PageA
. Каждый раз, когда я перехожу к PageB
и возвращаюсь к PageA
, создается новый ReceiverComponent
, и когда я нажимаю кнопку в EmitterComponent
, функция обратного вызова события ReceiverComponent
выполняется несколько раз.
Чтобы этого избежать, я отписываю ReceiverComponent
из myEvent
в ngOnDestroy
ngOnDestroy() {
this.eventService.myEvent.unsubscribe();
}
но это вызывает следующее исключение
EXCEPTION: Error during instantiation of ReceiverComponent!.
ORIGINAL EXCEPTION: Error: Cannot subscribe to a disposed Subject
Как я могу избежать этого? Как правильно отписаться?
Для лучшего понимания я создал этот plunker, где вы можете увидеть ошибку и некоторые комментарии в консоли.
Ответы
Ответ 1
Вы получаете подписку от .subscribe()
. Используйте метод unsubscribe()
для отмены подписки.
@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();
}
}
См. также
Ответ 2
Я думаю, что вы должны отменить подписку, как описано ниже:
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();
}
}
Фактически, EventEmitter
являются общими наблюдаемыми, то есть горячими наблюдаемыми. Вот ссылка, которая может вас заинтересовать: https://github.com/Reactive-Extensions/RxJS/blob/master/doc/gettingstarted/creating.md.
Надеюсь, это поможет вам,
Thierry