异步请求相互覆盖

458 阅读1分钟

问题环境

> angular 4.0

问题描述

多次触发根据不同条件查询数据时,且接口响应慢的时候,有时会出现前一个请求覆盖后面一个请求的现象,造成展现数据和查询条件不统一的现象。 如图,每次修改筛选条件均会触发请求,频繁操作时就会出现返回结果相互覆盖的情况。 github 示例问题链接:github.com/NG-ZORRO/ng…

代码举例

service.ts

getList(param: any){
  return this.httpClient.get(`/api/getList/${param}`);
}

component.ts

changeParam(param: any){
  this.service.getList(param).subscribe(res => {
    // res do something
    // dataList 是和页面绑定的数据
    this.dataList = res;
  })
}

解决思路

a. 保证每次请求结果获取的都是最后一次请求的 b. 频繁操作时,取消掉之前的请求

b方案更合理,a方案虽然可以解决问题,可能会存多个状体而且会发多次请求。

下面是具体的解决方案 (很简单哦)

  • angular4 以后引入了 HttpClient ,较之前的Promise,引入Observer,使用更顺手。

这里的请求其实是有返回的。Subscription 返回的新对象可以用来订阅和取消订阅。

可以在component.ts 全局声明一个Subscription 的变量控制取消订阅。

getListSubscription: Subscription;

changeParam(param: any){
  if(this.getListSubscription){
    this.getListSubscription.unsubscribe();
  }
  this.getListSubscription = this.service.getList(param).subscribe(res => {
    // res do something
    // dataList 是和页面绑定的数据
    this.dataList = res;
  })
}
  • 下面来说下另外一种方案解决,使用 rxjs 中的 switchMap 解决:
// 声明一个数据流
getList$ = new Subject();

ngOnInit(){
  this.getList$.pipe(
    switchMap(() => {
      return getList();
    })
  ).subscribe(res => {
    // res do something
    // dataList 是和页面绑定的数据
    this.dataList = res;
  })
}

getList(){
  return this.service.getList(param);
}

这两种方案都会再触发第二次请求前,将第一次发的请求置为cancel掉。