myml / myml.github.io

myml的个人网站
https://myml.dev
3 stars 0 forks source link

用RxJS把分次查询聚合为批量查询 #18

Open myml opened 6 years ago

myml commented 6 years ago

现有后端接口 /user?uid=1可根据uid查询用户信息,uid可为数组,例如/user?uid=1和/user?uid=1&uid=2&uid=3都是合法查询 在前端封装getUserInfo函数

getUserInfo(...uidList: number[]) {
    uidList=Array.from(new Set(uid))
    const params = uidList.reduce(
      (acc, uid) => params.append('uid', uid.toString()),
      new HttpParams(),
    );
    return this.http.get('/user', { params });
}

为了在angular更方便的使用,创建userinfo管道

transform(uid: number) {
  return getUserInfo(uid); 
}

前端页面使用uid|userinfo|async as user就能在模板使用用户信息 这样做缺陷是会发送多次请求,于是通过rxjs丰富的管道进行缓存,来实现把管道的参数累加到一次查询,然后结果再根据uid筛选

初优化:使用bufferTime

bufferTime会按时间把值搜集到数据,然后发送

pipe(
      bufferTime(10),
      filter(uidList => list.length > 0),
      switchMap(uidList => getUserInfo(...uidList)),
      share(),
)

当时间段内没有值bufferTime也会发送空数组,所以中间加了筛选。share用来在多个管道之间共享订阅 这样做缺陷是时间间隔不好定,定大了,界面会有一定空白期来等待buffer和接口查询。定小了,浪费cpu

二次优化:使用debounceTime

使用scan和debounceTime

pipe(
      scan((acc, uid) => acc.concat(uid), [] as number[]),
      debounceTime(10),
      switchMap(uidList => getUserInfo(...uidList)),
      share(),
)

这样就省去了不停止运行的定时器,也能最低程度的减少界面延迟显示。

解决BUG:share

上面实现的管道有个bug