我目前正在学习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);
}
答案 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> {
// ...
}
}