2017-04-12 75 views
9

我已經在我的應用程序中多次完成此操作。這很簡單,它應該工作...但是這次它不。Angular 2:Observable/Subscription not triggereding

我的問題:

我打電話對組件進行服務的方法,我組分B認購,但沒有反應,也沒有收到任何東西。 subscribe()不會觸發!

導航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部件

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

該組件觸發服務的方法:updateIBOsNavigation

IBOsNavigationElement組件

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

該組件訂購,應該列出並接收數據...

讓我們理清DI: 要考慮到IboDetailsGeneral處於下層在App的結構上,所以IboDetailsGeneral孩子IBOsNavigationElement

這就是爲什麼我添加NavigationElementsServiceIBOsNavigationElement的模塊:

NavigationModuleIBOsNavigationElement的模塊

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

控制檯:

CALLING updateIBOsNavigation功能

updateIBOsNavigation 「95」

CALLING updateIBOsNavigation功能AGAIN

updateIBOsNavigation 「測試」

此控制檯結果卻對我說:

  • 的方法被調用,所以沒有提供者錯誤。 與服務溝通OK

我的測試:

  • 我已經打過電話隨機方法IBOsNavigationElement(聽衆),並與服務之間的通信正常。
  • NavigationElementsService被添加到providers的唯一地方是NavigationModule,因此只有一個服務實例是正確的?然後,問題下面的鏈接解釋不會發生:Angular 2 observable subscription not triggering

我爲我「文字牆」真的很抱歉,但在這一點上我有點絕望。

任何幫助是令人滿意的,謝謝!

更新1:

第一個答案我已經試過幾件事情之後...

使用ReplaySubject

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

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

結果:當調用updateIBOsNavigation()subscribe()仍不觸發。

使用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); 
    } 
} 

結果:它進入subscribe()在初始化,但是當我打電話updateIBOsNavigation()subscribe()仍然不觸發。

使用BehaviorSubject V2:

我嘗試這樣的做法: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); 
    } 
} 

結果:同爲BehaviorSubject以前的應用程序。

更新2:

更多的樣本在整個網絡研究之後拼命地嘗試......

使用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); 
    } 
} 

結果:同以前BehaviorSubject嘗試......絕望正在崛起......

更新3:

以防萬一,我想確保NavigationElementsService

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

和導入時:

imports: [ 
     NavigationModule.forRoot() 
     ] 

結果:問題始終如此,subscribe()不會觸發,但在le因爲我知道有一個NavigationElementsService的實例。

+0

我加入更新與我絕望的嘗試...請結束我的折磨! xD – SrAxi

+0

嗨,你現在是否解決了這個問題? –

+0

@BonesandTeeth是的!謝謝! :D – SrAxi

回答

17

我認爲問題在於您的Subject類型使用Subject,在事件發生後訂閱的任何組件都不會接收到值。若要重播之前的價值給​​晚期用戶使用BehaviorSubjectReplaySubject而不是Subject

更多關於不同主題類型從http://reactivex.io/documentation/subject.html

行爲主題

當觀察者預訂BehaviorSubject時,它開始通過發射最近由源可觀察發出的項目(或種子/默認值,如果還沒有發射),然後繼續發射源Observable(s)發射的任何其他項目。

ReplaySubject

ReplaySubject發射到任何觀察者所有由源可觀察(多個)被髮射,該物品的,無論觀察者的訂閱時。

A BehaviorSubject設置時需要默認值。因此,你需要用某種價值創造它:

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

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

一個ReplaySubject不需要缺省值。

EDIT

當使用共享服務也是重要,以確保該服務正在僅在根模塊提供。如果它提供了多個地方,那麼組件可能不會獲得相同的實例。即使該服務是在根級別提供的,如果根級別和組件之間的模塊提供該服務,則會將新實例發送到依賴注入樹的分支。

希望這會有所幫助。

+0

或'ReplaySubject',它不需要初始默認值。 – jonrsharpe

+0

正確,要麼會替換最近的值。 –

+0

@TylerJennings謝謝!我試着用'BehaviorSubject'並刪除'asObservable()'。它第一次工作(在初始化時),但不是每次我調用該方法。我正在嘗試使用'ReplaySubject'。 – SrAxi

1

當我們在'providers'中包含一個服務時,它被實例化並且這個狀態在它的組件和子組件之間被維護。

而且,如果我們在兩個組件提供程序數組中都包含該服務,那麼它不再跟隨單例。國家將是獨立的,不會在他們之間分享。

因此,只包括您的服務在父組件或您的根組件。

我也遇到了這個問題,並在此解決方案的幫助下解決,https://stackoverflow.com/a/38034298/5730167