2017-07-07 107 views
1

我有一個統計應用程序。在我的頁面左側,我有主題列表,位於組頂部列表中。主要部分包含與主題和組相關的統計項目。角度跨服務溝通

另外我有幾個服務爲我的應用程序提供業務邏輯。爲了簡單起見,我們來談談其中三個:ThemeSerivce,GroupServiceStatisticsService

最終用戶可以操作主題和組列表(添加或刪除項目),每次更改後我都必須重新計算統計信息。在這個應用程序中,我使用受試者Subsubption from rx.js來跟蹤這種變化。

所以,在我的組件我可以寫這樣的事:

GroupComponent

removeGroup() { 
     this.groupService.removeGroup(this.group); 
     this.statisticsService.updateStatistics(); 
     } 

ThemeComponent

removeTheme() { 
    this.themeService.removeTheme(this.theme); 
    this.statisticsService.updateStatistics(); 
    } 

但在邏輯上,這些組件沒有了解統計信息。當然,我可以移動的依賴StatisticsServiceThemeServiceGroupService,但我將不得不調用statisticsService.updateStatistics()每從而改變主題或者組的收集方法。這就是爲什麼我想通過訂閱實現直接跨服務通信的原因。

最後我的問題:

  1. 這是個好主意呢?

  2. 如果沒關係,實現它的最好方法是什麼? 當我使用認購在分量I註冊它在ngOnInit()方法和ngOnDestroy()退訂防止內存泄漏。 我可以在服務的構造函數中訂閱它嗎?何時何地我應該取消訂閱?或者,當我在App模塊級別註冊我的服務作爲提供者時,可能沒有必要?

回答

0

StatisticsService應該訂閱主題和組列表。您的個人組件只應訂閱其各自的服務(ThemeComponent to ThemeService,Group to Group等)。

爲簡單起見,我只關注ThemeService,但GroupService與此類似。當調用remove時,ThemeService應該有一個內部的SubjectSubject下一個值(可能是整個新列表)。

StatisticsService將訂閱ThemeService可觀察並在更改後重新計算。它看起來像這樣

/* theme.service.ts */ 
@Injectable() 
export class ThemeService { 
    private _list$ = new Subject<ThemeList>(); 

    get list(): Observable<ThemeList> { 
     return this._list$.asObservable(); 
    } 

    set list(newList: ThemeList) { 
     this._list$.next(newList); 
    } 
} 


/* statistics.service.ts */ 
@Injectable() 
export class StatisticsService { 
    private _calculation$ = new Subject<StatisticResult>(); 

    constructor(private themeService: ThemeService) { 
     themeService.list.subscribe((themeList: ThemeList) => this.updateCalculation(themeList)); 
    } 

    get calculation(): Observable<StatisticResult> { 
     return this._calculation$.asObservable(); 
    } 

    updateCalculation(newData: ThemeList | GroupList) { 
     // ... do stuff 
     this._calculation.next(statisticResult); 
    } 
} 


/* statistics.component.ts */ 
@Component({ 
    selector: 'statistics', 
    template: '<p>{{ statisticResult$ | async }}</p>' 
}) 
export class StatisticsComponent { 
    statisticResult$: Observable<StatisticResult>; 

    constructor(private statisticsService: StatisticsService) { 
     this.statisticResult$ = statisticsService.calculation; 
    } 
}