角度跨服务通信 [英] Angular cross-service communication

查看:90
本文介绍了角度跨服务通信的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a statistics application. On the left side of my page I have list of themes, on the top - list of groups. The main part contains statistics items related to both theme and group.

我还有一些服务,可以为我的应用程序提供业务逻辑.为了简单起见,我们将讨论其中三个: ThemeSerivce,GroupService StatisticsService .

Also I have several services which provide business logic for my application. For simplicity let's talk about three of them: ThemeSerivce, GroupService and StatisticsService.

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

End users could manipulate lists of themes and groups (add or remove items) and I have to recalculate statistics after each change. In this application I use Subjects and Subsription from rx.js to track such kind of changes.

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

So, in my components I could write something like this:

用于 GroupComponent

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

用于 ThemeComponent

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

但是从逻辑上讲,这些组件不必了解统计信息.当然,我可以将 StatisticsService 的依赖关系移到 ThemeService GroupService 中,但是随后我将不得不调用 statisticsService.updateStatistics()中更改主题或组集合的每种方法.这就是为什么我要实现带有订阅的直接跨服务通信.

But logically these components don't have to know about statistics. Of course I can move dependency of StatisticsService into ThemeService and GroupService, but then I will have to call statisticsService.updateStatistics() in every method which changes collection of themes or groups. That's why I want to implement direct cross-service communication with subscription.

最后是我的问题:

  1. 这是个好主意吗?

  1. Is it a good idea at all?

如果可以,实现它的最佳方法是什么?当我在组件中使用 Subscription 时,我会在 ngOnInit()方法中注册它,然后在 ngOnDestroy()中取消订阅,以防止内存泄漏.我可以在服务的构造函数中订阅它吗?我应该何时何地退订?或者当我在App模块级别将我的服务注册为提供程序时,也许没有必要吗?

If it's ok, what is the best way to implement it? When I use Subscription in components, I register it in ngOnInit() method and unsubscribe in ngOnDestroy() to prevent memory leaks. Could I subscribe it in service's constructor? And when or where should I unsubscribe? Or maybe it's not necessary when I register my services as provider on App module level?

推荐答案

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

StatisticsService should subscribe to the list of themes and groups. Your individual components should only subscribe to their respective services (ThemeComponent to ThemeService, Group to Group etc).

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

For simplicity, I'll just focus on the ThemeService but GroupService is similar. ThemeService should have an internal Subject when remove is called, the Subject will next a value (probably the entire new list).

StatisticsService 将订阅可观察的 ThemeService ,并在更改后重新计算.看起来像这样

StatisticsService will subscribe to the ThemeService observable and recalculate after change. It will look something like this

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

这篇关于角度跨服务通信的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆