取消先前的http请求并使用async

时间:2019-05-11 10:34:04

标签: angular rxjs angular7 rxjs6

我的组件显示选定的建筑物详细信息以及建筑物的建筑物单位(公寓)列表。这是一个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。

2 个答案:

答案 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');
    }
}