2017-07-07 109 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; 
    } 
}