Angular 4呼叫服务方法,包含先前服务方法调用的数据

时间:2018-03-24 11:24:39

标签: angular observable

我目前正在学习Angular,同时建立一个网站,旨在通过桌面竞赛管理器应用程序实时提供击剑比赛的结果。

我遇到了如何"链"可观察的订阅。 我已经成功了,但我非常确定必须有一个更优雅的解决方案。

当我路由到一场比赛时,我会在Id中传球以获得比赛,例如

getMatch(id: number){
    this._matchService.getMatch(id).subscribe
    (
      match => this.match = match,
      error => this.errorMessage = <any>error
    )

问题产生于匹配对象包含来自池中的ID,比赛中的比赛和击剑者。所以我需要使用getMatch的响应来获得竞争,击剑手和游泳池。

我目前正在这样做,但感觉不是很好。 我考虑重建API确实可以在一次通话中提供所有需要的数据,但我想让这项工作成功。

getMatch(id: number){
    this._matchService.getMatch(id).subscribe(
      match => {
        this.match = match;

        this._fencerService.getFencer(match.blueFencerId).subscribe(
          bf => this.blueFencer = bf,
          error => this.errorMessage = <any>error
        );

        this._fencerService.getFencer(match.redFencerId).subscribe(
          rf => this.redFencer = rf,
          error => this.errorMessage = <any>error
        );

        this._poolService.getPool(match.poolId).subscribe(
          pool => {
            this.pool = pool.name;

      this._competitionService.getCompetition(pool.competitionId).subscribe(
              comp => this.competitionName = comp.name
            )
          },
          error => this.errorMessage = <any>error
        )
      },
      error => this.errorMessage = <any>error
    )
  }

此外,这就是matchService方法的样子,以及其他服务的重复模式:

getMatch(id: number): Observable<IMatch>{
  return this.getPopulatedMatches().map((matches: IMatch[]) => 
     matches.find(p => p.id === id));
}

我不确定我是否在设计中做了一些根本性的错误,但是我想将所有服务调用分成几个单独的方法,就像这样。

ngOnInit() {
   getMatch();
   getPool(match.poolId);
   this.redFencer = getFencer(match.redFencerId);
   this.blueFencer = getFencer(match.blueFencerId);
}

1 个答案:

答案 0 :(得分:1)

嵌套的.subscribe()块是一种反模式。

试试这个:

对于rxjs&gt; 5.5.2:

  getMatch(id: number) {
    const match$ = this._matchService.getMatch();

    const blueFencer$ = match$.pipe(
      flatMap(({ blueFencerId }) => this._matchService.getFencer(blueFencerId)),
    );

    const redFencer$ = match$.pipe(
      flatMap(({ redFencerId }) => this._matchService.getFencer(redFencerId)),
    );

    const pool$ = match$.pipe(
      flatMap(({ poolId }) => this._poolService.getPool(poolId)),
    );

    const competition$ = pool$.pipe(
      flatMap(({ competitionId }) =>
        this._competitionService.getCompetition(competitionId),
      ),
    );

    return { match$, blueFencer$, redFencer$, pool$, competition$ };
  }

对于rxjs&lt; 5.5.2:

  getMatch(id: number) {
    const match$ = this._matchService.getMatch();

    const blueFencer$ = match$
      .flatMap(({ blueFencerId }) => this._matchService.getFencer(blueFencerId));

    const redFencer$ = match$
      .flatMap(({ redFencerId }) => this._matchService.getFencer(redFencerId));

    const pool$ = match$
      .flatMap(({ poolId }) => this._poolService.getPool(poolId));

    const competition$ = pool$
      .flatMap(({ competitionId }) =>
        this._competitionService.getCompetition(competitionId));

    return { match$, blueFencer$, redFencer$, pool$, competition$ };
  }

然后在您的组件中,您可以订阅每个单独的流并执行您想要的任何操作。

编辑: 如果您希望在MatchService

中创建流
export class MatchService {
  match$ = this.getMatch();

  blueFencer$ = this.match$.pipe(
    flatMap(({ blueFencerId }) => this.getFencer(blueFencerId)),
  );

  redFencer$ = this.match$.pipe(
    flatMap(({ redFencerId }) => this.getFencer(redFencerId)),
  );

  pool$ = this.match$.pipe(
    flatMap(({ poolId }) => this._poolService.getPool(poolId)),
  );

  competition$ = this.pool$.pipe(
    flatMap(({ competitionId }) =>
      this._competitionService.getCompetition(competitionId),
    ),
  );

  constructor(
    private _poolService: PoolService,
    private _competitionService: CompetitionService,
  ) {}

  getMatch(id: number): Observable<any> {
    // ...
  }

  getFencer(id: number): Observable<any> {
    // ...
  }
}