【问题标题】:Cancel previous, non-identical requests in Angular在 Angular 中取消以前的不相同的请求
【发布时间】:2021-09-06 15:24:37
【问题描述】:

我正在尝试在 Angular 应用程序中获取传单地图的数据。对于每个缩放级别,我需要不同的分辨率数据,这就是为什么在 moveend 上我再次调用后端。

ma​​p.component

    // Every time a movement is done on the map the calls are done again.
    this.map.on('moveend', () => {
      this.mapService.drawHeatMap();
    });

ma​​p.service.ts

  public drawHeatMap(): void {
    this.fetchData().subscribe((data) => {
      // DO STUFF WITH DATA
    });
  }
private fetchData(): Observable<Leaflet.HeatLatLngTuple[]> {
    return this.http.get<ResponseType>(URL).pipe(
      map(({ data }: ResponseType) => {
        return data.map((data: any) => {
          // PARSE DATA
        });
      })
    );
  }

在测试过程中,我发现滚动进出很多会使对我的 API 的调用堆积起来,这是我想要避免的。

当我尝试使用 switchMap() 取消挂起的呼叫时,我没有得到想要的结果,因为呼叫不相同...

来自两个不同调用的请求 URL 示例:

.../api/ZoomLevel=10&amp;swLong=3&amp;neLong=5&amp;swLat=50&amp;neLat=51

.../api/ZoomLevel=11&amp;swLong=2&amp;neLong=4&amp;swLat=49&amp;neLat=50

帮助取消之前的通话虽然不相同将不胜感激。

【问题讨论】:

    标签: angular typescript rest rxjs


    【解决方案1】:

    发生这种情况是因为 HTTP 请求 observable 和事件一没有通过一个 pipe 和一个 subscribe 相互链接。

    此外,在此类事件中,最好使用RxJS debounceTime 运算符来减少HTTP 调用次数。

    您可以尝试以下方法:

    fromEvent(this.map, 'moveend')
      .pipe(
        debounceTime(300), // This will prevent calling the drawHeatMap within 300ms more than one time.
        switchMap(() => this.mapService.drawHeatMap())
      )
      .subscribe();
    

    在你的map.service:

    public drawHeatMap(): Observable<any> {
      return this.fetchData().pipe(
        tap((data) => {
          // DO STUFF WITH DATA
        })
      );
    }
    

    【讨论】:

      【解决方案2】:

      现在正在发生什么 - 您正在对每个事件进行调用。换句话说,制作流。相反,您需要一个流,以取消先前的呼叫。

      ma​​p.component

      fromEvent(this.map, 'moveend').pipe(
        switchMap(() => this.mapService.drawHeatMap())
      ).subscribe();
      

      ma​​p.service.ts

        public drawHeatMap(): void {
          return this.fetchData();
        }
      

      附言显然我还没有测试过,所以不确定fromEvent(this.map, 'moveend') 是否是获取外部流的正确方法。请提供this.map API 以获得更详细的答案。

      【讨论】:

        【解决方案3】:

        感谢您的意见。最后,我无法将this.map.on 包装在fromEvent() 运算符中,所以我创建了一个mapEvent$ 主题,每次Leaflet 注册moveend 时都会触发该主题。然后我订阅它,而不是使用 switchMap() 我在我的服务中注册活动订阅并手动取消之前的呼叫。这样我就有了更多的控制权,并且不必从updateMap()返回冷的可观察对象

        ma​​p.component.ts

        public ngOnInit(): void {
          this.initMapEvents();
          this.map.on('moveend', (val) => {
            this.mapService.mapEvent$.next(val);
          });
        }
        
        private initMapEvents(): void {
          this.mapService.updateMap();
          this.mapService.mapEvent$
            .pipe(debounceTime(ms), takeUntil(this.unsubscribe))
            .subscribe(() => {
              this.mapService.updateMap();
          });
        }
        

        ma​​p.service.ts

        public mapEvent$ = new Subject();
        private activeSubscription!: Subscription;
        
        public updateMap(): void {
          // cancel previous call
          if (this.activeSubscription) {
            this.activeSubscription.unsubscribe();
          }
        
          this.activeSubscription = this.fetchData().subscribe((data) => {
            // DO STUFF WITH DATA
          });
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-04-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多