2016-08-01 28 views
2

Ich habe eine "AppService", die ich verwende, um die Interaktion zwischen allen meinen Komponenten (Formulare, Navigationen, etc) zu behandeln.angular2 Zerstörung von Subskriptionen auf Sicht zerstören

Mein Dienst verfügt über viele Ereignisemitter, die von den Komponenten abonniert werden (Ergebnisse, Element ausgewählt, Formular gebucht usw.).

Wenn eine neue Ansicht angezeigt wird, abonniert sie die appService-Ereignisse, die sie benötigt. Nun ist das Problem, wenn ich zu einer anderen Ansicht (Formular) navigiere, die nicht mehr benötigte Ansicht wird zerstört, aber ihre Abonnements werden immer noch aufgerufen ...! Ich finde, dass ich auf alle Subskriptionen referenziere und explizit einen massiven Textbaustein für eine einfache Aufgabe abbestelle. Was mache ich falsch? Wie kann ich dies verdeutlichen?

Beispielcode:

export class VendorsForm { 
    constructor(private appService: AppServiceMain) 
    { 
      this.appService.onSearchResultSelected$.subscribe((selectedEntity) => { 
      //detailed view of this item 
      this.model = selectedEntity; 
      this.appService.setFormIsShowingDetail(); 
     }) 
    }); 

    } 
} 

jetzt in einer anderen Komponente:

export class CustomersForm { 
    constructor(private appService: AppServiceMain) 
    { 
      this.appService.onSearchResultSelected$.subscribe((selectedEntity) => { 
      //detailed view of this item 
      this.model = selectedEntity; this.appService.setFormIsShowingDetail(); 
     }) 
    }); 

    } 
} 

nur als Referenz, hier ist der Service und die Ereignis Aufruf Komponenten:

export class AppServiceMain { 
    public onSearchResultSelected$: EventEmitter<IEntity>; 
     setSelectedEntity(ent: IEntity) 
     { 
      this.formstate = states.EntitySelected; 
      this.onSearchResultSelected$.emit(ent); 
     } 

Ereignis aufrufen Komponente

export class ResultsComponent { 
    rowDblClick(ev$) 
    { 
     this.appService.setSelectedEntity(ev$.data); 
    } 

Ich verstehe, wie diese suscriptions zu entfernen, wenn ich will. Das Problem ist, dass meine Formulare ziemlich groß und funktional sind und ich Tonnen von Nicht-Standard-Referenzen habe. Gibt es nicht eine Möglichkeit, automatisch zu hören, wenn die Ansicht zerstört wird? Ich finde das alles manuell zu zerstören, um ziemlich fehleranfällig zu sein.

+0

kleine Bemerkung: meine ResultsComponent und AppService sind beide immer lebendig und Sigle Instanz – user5328504

+0

Könnten Sie klären, warum die Implementierung 'ngOnDestroy' Methode für Sie nicht funktioniert? Für den Fall, dass Sie verpasst haben: [OnDestroy] (https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html) – leovrf

Antwort

3

Wenn Sie unbedingt abonnieren, dann abmelden auch how to unsubscribe several subscriber in angular 2

+2

danke Günter, eigentlich ist das, was ich gerade mache .... ich bekomme ein Griff von allen Abonnements in einem Array..aber ich hasse es so zu tun ... Ich habe auch gesehen, es gibt eine Möglichkeit, es mit "async pipes" zu automatisieren, aber ist auch schrecklich ... Ich fühle mich wie eckig2 treibt die verrücktesten Muster überall hin ... wie gehst DU damit um? Vielleicht ist dieser Ansatz nicht gut für das App-Flow-Management? – user5328504

+0

Ich sehe kein Problem mit '| async' noch mit unsubscribe. –

+0

Ich werde Ihre als Antwort markieren - nur sagen, diese Syntax ist CODE SMELL – user5328504

4

this.someSubscription = this.appService.onSearchResultSelected$.subscribe((selectedEntity) => 

ngOnDestroy() { 
    this.someSubscription.unsubscribe(); 
} 

Sehen Sie brauchen keine Reihe von Abonnements zwingend auch haben. Verwenden Sie RxJS.Subject und takeUntil Combo zu handhaben Abonnements wie ein Chef:

import {Subject} from "rxjs/Subject"; 

@Component(
    { 
     moduleId: __moduleName, 
     selector: 'my-view', 
     templateUrl: '../views/view-route.view.html', 
    } 
) 
export class ViewRouteComponent implements OnDestroy 
{ 
    componentDestroyed$: Subject<boolean> = new Subject(); 

    constructor(protected titleService: TitleService) 
    { 
     this.titleService.emitter1$ 
      .takeUntil(this.componentDestroyed$) 
      .subscribe(
      (data: any) => 
      { 
       // ... do something 1 
      } 
     ); 

     this.titleService.emitter2$ 
      .takeUntil(this.componentDestroyed$) 
      .subscribe(
      (data: any) => 
      { 
       // ... do something 2 
      } 
     ); 

     // ... 

     this.titleService.emitterN$ 
      .takeUntil(this.componentDestroyed$) 
      .subscribe(
      (data: any) => 
      { 
       // ... do something N 
      } 
     ); 
    } 

    ngOnDestroy() 
    { 
     this.componentDestroyed$.next(true); 
     this.componentDestroyed$.complete(); 
    } 
} 
+0

das ist gute Sachen – user5328504

0

so, wie ich es tue, ist:

this.subscriptions.push(this.appService.onSearchResultSelected$.subscribe((selectedEntity) => {})); 

ngOnDestroy() { 
    this.subscriptions.forEach((subscription) => { 
     subscription.unsubscribe(); 
    }); 
} 

Sie können n Anzahl der Abonnements mit dieser Art und Weise handhaben, müssen Sie nur drücken jedes Mal, wenn Sie das Abonnement verwenden.

Dies ist der einfachste und einfachste Weg.