2016-01-21 19 views
21

W mojej aplikacji mam pewne komponenty, które komunikują się za pomocą EventService.Angular2, wypisanie z wydarzenia w ngOnDestroy

@Injectable() 
export class EventService { 
    public myEvent: EventEmitter<any> = new EventEmitter(); 
    constructor() {} 
} 

Usługa ta jest wstrzykiwany w EmitterComponent emitującego zdarzenie gdy przycisk zostanie kliknięty

@Component({ 
    selector: 'emitter', 
    template: `<button (click)="onClick()">Click me</button>`, 
}) 
export class EmitterComponent { 
    constructor(private eventService:EventService) {} 
    onClick() { 
    this.eventService.myEvent.emit(); 
    } 
} 

iw ReceiverComponent że zgadza się z imprezy i dla każdego zdarzenia odebranych przyrostach licznik

@Component({ 
    selector: 'receiver', 
    template: `Count: {{count}}`, 
}) 
export class ReceiverComponent { 
    public count = 0; 
    constructor(private eventService:EventService) { 
    this.eventService.myEvent.subscribe(() => this.count++;); 
    } 
} 

Aplikacja ma wiele widoków (w tym przykładzie tylko dwa): PageA i PageB. EmitterComponent i ReceiverComponent są w PageA. Za każdym razem, gdy przechodzę do PageB i wracam do PageA, tworzony jest nowy ReceiverComponent i po kliknięciu przycisku w EmitterComponent funkcja wywołania zwrotnego zdarzenia ReceiverComponent jest wykonywana kilka razy.

Aby tego uniknąć wypisać ReceiverComponent z myEvent w ngOnDestroy

ngOnDestroy() { 
    this.eventService.myEvent.unsubscribe(); 
} 

ale powoduje to następujący wyjątek

EXCEPTION: Error during instantiation of ReceiverComponent!. 
ORIGINAL EXCEPTION: Error: Cannot subscribe to a disposed Subject 

Jak mogę tego uniknąć? Jak poprawnie zrezygnować z subskrypcji?

Dla lepszego zrozumienia stworzyłem ten numer plunker, w którym można zobaczyć błąd i komentarze w konsoli.

Odpowiedz

30

Otrzymujesz subskrypcję od .subscribe(). Użyj metody unsubscribe(), aby anulować subskrypcję.

@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(); 
    } 
} 

Zobacz także

+0

To jest dokładnie to, co zrobiłem, ale to powoduje „Błąd: Nie można zapisać się do zbytej Temat” Kiedy zmienić pogląd na stronaB i wrócić do strony A – TizianoL

+3

Nie wyglądają to samo dla mnie. Czy czegoś brakuje? W twoim pytaniu używasz 'this.eventService.myEvent.unsubscribe();' vs 'subscription.unsubscribe();'. –

+1

Och, przepraszam, moja zła, nie zauważyłem różnicy. Teraz działa, wielkie dzięki! – TizianoL

2

myślę, że powinien zrezygnować z subskrypcji, jak opisano poniżej:

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(); 
    } 
} 

W rzeczywistości, EventEmitter s są wspólne obserwowalne, tj. Gorące obserwowalne. Oto link, który może Cię zainteresować: https://github.com/Reactive-Extensions/RxJS/blob/master/doc/gettingstarted/creating.md.

Nadzieję, że to pomaga, Thierry