我的组件显示选定的建筑物详细信息以及建筑物的建筑物单位(公寓)列表。这是一个html组件:
<div *ngIf="$building | async as building">
...
<div *ngIf="$buildingUnits | async as buildingUnits">
...
</div>
</div>
这是组件控制器:
@Component({
selector: 'building-dashboard',
templateUrl: './building-dashboard.component.html',
styleUrls: ['./building-dashboard.component.scss']
})
export class BuildingDashboardComponent implements OnInit {
private buildingId: number;
private $building: Observable<Building>;
private $buildingUnits: Observable<BuildingUnit[]>;
ngOnInit() {
this.$building = this.route.paramMap.pipe(
tap((params: ParamMap) => {
this.buildingId = Number(params.get('id'));
}),
switchMap((params: ParamMap) => {
return this.buildingService.getBuilding(this.buildingId);
})
);
this.$buildingUnits = this.route.paramMap.pipe(
switchMap((params: ParamMap) => {
let buildingId = Number(params.get('id'));
return this.buildingUnitsService.getBuildingUnits(buildingId);
})
);
}
reloadBuildingUnits() {
this.$buildingUnits = this.buildingUnitsService.getBuildingUnits(this.buildingId);
}
}
建筑物的ID由路径参数获得。当建筑物ID更改时,我需要重新加载建筑物详细信息和buildingUnits列表。用户可以通过单击按钮激活 reloadBuildingUnits()方法。在这种情况下,我需要重新加载buildingUnits列表,并取消之前的http请求(如果尚未完成)。我不知道该怎么做。可能我应该在控制器中先订阅然后取消订阅,而不要使用异步?使用promise而不是可观察的可能会更好吗?我是Angular的新手,如果有任何改进建议,我将非常感谢。我正在使用Angular 7.2.0和rxjs 6.3.3。
答案 0 :(得分:0)
您可以在按钮单击时使用fromEvent
运算符,因此如果尚未完成,则它将取消订阅先前的请求流:
@ViewChild('btn') btn;
ngAfterViewInit() {
this.$buildingUnits = fromEvent(this.btn.nativeElement, 'click').pipe(
switchMap(() => this.buildingUnitsService.getBuildingUnits(this.buildingId)),
)
}
您还可以将$buildingUnits
初始化为默认值,并使用switchMap
在方法调用时重新分配Observable(但它不会取消先前的请求,尽管您仍然会得到最新的请求):
$buildingUnits: Observable<any> = of([]);
reloadBuildingUnits() {
this.$buildingUnits = this.$buildingUnits.pipe(
switchMap(() => this.buildingUnitsService.getBuildingUnits(this.buildingId)
);
}
答案 1 :(得分:-1)
按钮单击可观察到的发射和路由器参数可观察到的发射与Combinelatest运算符绑定在一起,因此,每当路由器参数更改或执行按钮单击操作时,switchmap都会取消先前的http请求并触发新的http请求。
export class BuildingDashboardComponent implements OnInit {
private buildingId: number;
private $building: Observable<Building>;
private $buildingUnits: Observable<BuildingUnit[]>;
reloadClick$ = new BehaviorSubject<any>('initValue');
constructor(
private buildingService: ExchangeService,
private route: ActivatedRoute) { }
ngOnInit() {
this.$building = this.route.paramMap.pipe(
tap((params: ParamMap) => this.buildingId = Number(params.get('id'))),
switchMap((params: ParamMap) => this.buildingService.getBuilding(this.buildingId))
);
this.$buildingUnits = this.route.paramMap.pipe(combineLatest(this.reloadClick$)).pipe(
switchMap(([params, _]) => this.buildingService.getBuildingUnits(Number(params.get('id'))))
);
}
reloadBuildingUnits() {
this.reloadClick$.next('reloadClick');
}
}