首页 文章

角度跨服务通信

提问于
浏览
1

我有一个统计应用程序 . 在我的页面的左侧,我有主题列表,在顶部 - 组列表 . 主要部分包含与主题和组相关的统计项 .

我还有几个服务为我的应用程序提供业务逻辑 . 为简单起见,我们来谈谈其中三个:ThemeSerivce,GroupService和StatisticsService .

最终用户可以操作主题和组列表(添加或删除项目),我必须在每次更改后重新计算统计信息 . 在这个应用程序中,我使用来自rx.js的Subjects和Subsription来跟踪这种变化 .

所以,在我的组件中,我可以这样写:

对于GroupComponent

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

for ThemeComponent

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

但从逻辑上讲,这些组件不必了解统计数据 . 当然,我可以将StatisticsService的依赖项移动到ThemeService和GroupService中,但是我必须在每个更改主题或组集合的方法中调用statisticsService.updateStatistics() . 这就是我想要通过订阅实现直接跨服务通信的原因 .

最后我的问题:

  • 这根本不是一个好主意吗?

  • 如果没关系,实施它的最佳方法是什么?当我在组件中使用Subscription时,我在ngOnInit()方法中注册它并取消订阅ngOnDestroy()以防止内存泄漏 . 当我在App模块级别注册我的服务作为提供者时,我是否可以在服务中订阅's constructor? And when or where should I unsubscribe? Or maybe it'?

1 回答

  • 0

    StatisticsService 应订阅主题和组列表 . 您的个人组件应仅订阅其各自的服务(ThemeComponent to ThemeService,Group to Group etc) .

    为简单起见,我只关注 ThemeServiceGroupService 类似 . ThemeService 应该有一个内部 Subject 当调用remove时, Subject 将接下来一个值(可能是整个新列表) .

    StatisticsService 将订阅 ThemeService observable并在更改后重新计算 . 它看起来像这样

    /* 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;
        }
    }
    

相关问题