2017-04-12 5 views
9

Ich habe dies mehrmals in meiner App getan. Es ist einfach, es sollte funktionieren ... Aber dieses Mal nicht.Angular 2: Observable/Subscription nicht triggern

Mein Problem:

ich eine Methode in einem Dienst von einer Komponente A nenne, meine Komponente B gezeichnet ist, aber nicht reagiert noch nichts erhalten. subscribe() löst nicht aus!

navigations elements.service.ts

@Injectable() 
export class NavigationElementsService { 
    updateIBOsNavigation$: Observable<any>; 

    private updateIBOsNavigationSubject = new Subject<any>(); 

    constructor() { 
     this.updateIBOsNavigation$ = this.updateIBOsNavigationSubject.asObservable(); 
    } 

    updateIBOsNavigation(navigationData) { 
     log.d('updateIBOsNavigation', JSON.stringify(navigationData)); 
     this.updateIBOsNavigationSubject.next(navigationData); 
    } 
} 

IboDetailsGeneral Komponente

export class IboDetailsGeneral implements OnInit, OnDestroy { 
    id: string; 
    private sub: any; 

    constructor(private route: ActivatedRoute, private iboService: IBOsService, private navigationService: NavigationElementsService) { 
     this.sub = this.route.params.subscribe(params => { 
      this.id = params['id']; 

      console.log('CALLING updateIBOsNavigation FUNCTION'); 
      this.navigationService.updateIBOsNavigation(this.id); 
     }); 
    } 

    ngOnInit() { 
     console.log('CALLING updateIBOsNavigation FUNCTION AGAIN'); 
     this.navigationService.updateIBOsNavigation('test'); 
    } 

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

Diese Komponente löst die Methode des Service: updateIBOsNavigation.

IBOsNavigationElement Komponente

export class IBOsNavigationElement implements OnInit { 
    private id: string; 

    constructor(private navigationService: NavigationElementsService) { 
     this.navigationService.updateIBOsNavigation$.subscribe((navigationData) => { 
       log.d('I received this Navigation Data:', JSON.stringify(navigationData)); 
       this.id = navigationData; 
      } 
     ); 
    } 

    ngOnInit() { 
    } 
} 

Diese Komponente gezeichnet wird, sollte sie die Daten aufgeführt und erhalten ...

Lasst uns DI aussortieren: berücksichtigen, dass IboDetailsGeneral in einer unteren Schicht auf der App-Struktur, so IboDetailsGeneral ist Kind von IBOsNavigationElement. Diese

ist, warum ich NavigationElementsService in IBOsNavigationElement hinzufügen 's-Modul:

NavigationModule ist IBOsNavigationElement' s Modul

@NgModule({ 
    imports: [ 
     // A lot of stuff 
    ], 
    declarations: [ 
     // A lot of stuff 
     IBOsNavigationElement 
    ], 
    exports: [ 
     // A lot of stuff 
    ], 
    providers: [ 
     NavigationElementsService 
    ] 
}) 

Console:

CALLING updateIBOsNavigation FUNKTION

updateIBOsNavigation "95"

CALLING updateIBOsNavigation Funktion erneut

updateIBOsNavigation "test"

Diese Konsole Ergebnisse mir sagt, dass:

  • Die Methode aufgerufen wird, so dass keine Anbieterfehler. Die Kommunikation mit dem Service ist OK.

Meine Tests:

  • Ich habe versucht, in IBOsNavigationElementeine zufällige Methode aufrufen (der Hörer), und die Kommunikation mit der Service ist gut.
  • Der einzige Ort, wo NavigationElementsService zu providers hinzugefügt wird, ist in NavigationModule, so gibt es nur eine Instanz der Service-Recht? Dann erklärte das Problem in dem folgenden Link findet nicht statt: Angular 2 observable subscription not triggering

Ich bin wirklich leid für meine ‚Wand des Textes‘ aber an dieser Stelle Ich bin ein bisschen verzweifelt.

Jede Hilfe ist appreated, danke!

Update 1:

Nach der ersten Antwort, die ich einige Dinge ausprobiert haben ...

ReplaySubject Verwendung:

@Injectable() 
export class NavigationElementsService { 
    public updateIBOsNavigation$ = new ReplaySubject(); 

    updateIBOsNavigation(navigationData) { 
     log.d('updateIBOsNavigation', JSON.stringify(navigationData)); 
     this.updateIBOsNavigation$.next(navigationData); 
    } 
} 

Ergebnis: Wenn updateIBOsNavigation() Aufruf, subscribe() ist nach wie vor nicht auslösend.

Mit BehaviorSubject:

@Injectable() 
export class NavigationElementsService { 
    updateIBOsNavigationSubject = new BehaviorSubject<any>(''); 
    updateIBOsNavigation$ = this.updateIBOsNavigationSubject.asObservable(); 

    updateIBOsNavigation(navigationData) { 
     log.d('updateIBOsNavigation', JSON.stringify(navigationData)); 
     this.updateIBOsNavigationSubject.next(navigationData); 
    } 
} 

Ergebnis: Es tritt subscribe() bei der Initialisierung, aber wenn ich updateIBOsNavigation() nennen, subscribe() ist noch nicht ausgelöst wird.

Mit BehaviorSubject v2:

Ich habe versucht, diesen Ansatz: behaviourSubject in angular2 , how it works and how to use it

@Injectable() 
export class NavigationElementsService { 
    public updateIBOsNavigation$: Subject<string> = new BehaviorSubject<string>(null); 

    updateIBOsNavigation(navigationData) { 
     log.d('updateIBOsNavigation', JSON.stringify(navigationData)); 
     this.updateIBOsNavigation$.next(navigationData); 
    } 
} 

Ergebnis: Wie in früheren Anwendung von BehaviorSubject.

Update 2:

Weitere Proben von verzweifelten Versuche, nach der ganzen Bahn Erforschung ...

Mit BehaviorSubject v3:

@Injectable() 
export class NavigationElementsService { 
    updateIBOsNavigation$: Observable<any>; 
    updateIBOsNavigationSubject = <BehaviorSubject<any>> new BehaviorSubject([]); 

    constructor() { 
     this.updateIBOsNavigation$ = this.updateIBOsNavigationSubject.asObservable(); 
    } 

    updateIBOsNavigation(navigationData) { 
     log.d('updateIBOsNavigation()', JSON.stringify(navigationData)); 
     this.updateIBOsNavigationSubject.next(navigationData); 
    } 
} 

Ergebnis: Wie in früheren BehaviorSubject Versuche ... Die Verzweiflung steigt ...

Update 3:

Nur für den Fall, ich wollte sicherstellen, dass NavigationElementsService ist ein Singletons:

export class NavigationModule { 
    static forRoot() { 
     return { 
      ngModule: NavigationModule, 
      providers: [NavigationElementsService] 
     }; 
    } 
} 

Und beim Import:

imports: [ 
     NavigationModule.forRoot() 
     ] 

Ergebnis: Gleiches Problem wie immer, subscribe() nicht auslösend, aber bei le Ich weiß, dass es eine Instanz von NavigationElementsService gibt.

+0

Ich füge Updates mit meinen verzweifelten Versuchen hinzu ... Bitte beenden Sie meine Folter! xD – SrAxi

+0

Hallo, haben Sie dieses Problem jetzt gelöst? –

+0

@BonesandTeeth Ja! Vielen Dank! : D – SrAxi

Antwort

17

Ich denke, die Frage ist Ihr Subject Typ Mit Subject, jede Komponente, die abonniert hat, nachdem ein Ereignis ausgelöst hat, wird keinen Wert erhalten. Verwenden Sie BehaviorSubject oder ReplaySubject anstelle von Subject, um den vorherigen Wert zu späten Abonnenten wiederzugeben.

Mehr auf verschiedenen Fachtypen von http://reactivex.io/documentation/subject.html

Verhalten Gegenstand

Wenn ein Beobachter an einen BehaviorSubject abonniert, es beginnt mit dem Element emittiert zuletzt von der Quelle beobachtbare emittiert (oder einem Samen/default value, wenn noch keiner ausgegeben wurde, und sendet dann weitere Elemente aus, die später von den Observable (s) der Quelle ausgegeben werden.

ReplaySubject

ReplaySubject aussendet jedem Beobachter alle Elemente, die Observable die von der Quelle emittiert wurden (n), unabhängig davon, wenn der Beobachter abonniert.

Ein BehaviorSubject erfordert einen Standardwert bei der Einrichtung. So müssen Sie es mit irgendeiner Art von Wert zu schaffen:

updateIBOsNavigationSubject = new BehaviorSubject<any>(''); 
updateIBOsNavigation$ = this.updateIBOsNavigationSubject.asObservable(); 

updateIBOsNavigation(navigationData) { 
    log.d('updateIBOsNavigation', JSON.stringify(navigationData)); 
    this.updateIBOsNavigationSubject.next(navigationData); 
} 

A ReplaySubject keinen Standardwert erfordern.

EDIT

Wenn ein Shared Service verwendet es auch wichtig, um sicherzustellen, dass der Service an der Root-Modul bereitgestellt NUR wird. Wenn mehrere Stellen zur Verfügung stehen, erhalten die Komponenten möglicherweise nicht dieselbe Instanz. Selbst wenn der Dienst auf der Stammebene bereitgestellt wird, wird, wenn ein Modul zwischen der Stammebene und Ihrer Komponente den Dienst bereitstellt, eine neue Instanz in den Zweig der Dependency-Injection-Struktur gesendet.

Hoffe, das hilft.

+0

Oder 'ReplaySubject', für das kein anfänglicher Standardwert erforderlich ist. – jonrsharpe

+0

Korrigieren, entweder wird der neueste Wert ersetzt. –

+0

@TylerJennings Danke! Ich habe versucht mit 'BehaviorSubject' und' asObservable() 'zu entfernen. Es funktionierte das erste Mal (init), aber nicht jedes Mal, wenn ich die Methode anrufe. Ich versuche es jetzt mit 'ReplaySubject'. – SrAxi

1

Wenn wir einen Dienst in "Providers" einschließen, wird er instanziiert und dieser Status wird zwischen seiner Komponente und seinen untergeordneten Komponenten beibehalten.

Und wenn wir den Dienst in beiden Komponenten Provider-Array enthalten, dann ist es nicht mehr Singleton folgen. Der Staat wird unabhängig sein und nicht zwischen ihnen geteilt werden.

Fügen Sie also Ihren Dienst nur zur übergeordneten Komponente oder zur Stammkomponente hinzu.

Auch ich habe dieses Problem gelöst und mit Hilfe dieser Lösung hier gelöst, https://stackoverflow.com/a/38034298/5730167.