Angular HTTP 请求复用方案

引言

Web应用,由于组件化大行其道,诞生了一个问题。typescript

image.png

如上图所示,顶部导航栏组件须要请求当前登陆用户的姓名,左侧菜单栏组件须要请求当前登陆用户的菜单权限,根据后台的接口设计,二者都须要在应用初始化时获取当前登陆用户。json

导航栏发起HTTP请求,获取当前登陆用户信息。网络

菜单栏发起HTTP请求,获取当前登陆用户信息。组件化

二者请求到的数据是相同的,彻底能够共用一个请求来完成这个任务,请求两次无疑耗费网络资源。post

可是就这么一个简单的任务,却迭代了好几个实现版本才完美解决。学习

实现

问题示范

以下所示,屡次请求同一接口数据,实际业务场景确定是跨组件的,这里只是举一个最简单的例子:this

export class AppComponent implements OnInit {

  constructor(private httpClient: HttpClient) {
  }

  ngOnInit(): void {
    this.getTeachers();
  }

  getTeachers(): void {
    this.request().subscribe((teachers: Array<Teacher>) => {
      console.log('request - 1', teachers);
    });
    this.request().subscribe((teachers: Array<Teacher>) => {
      console.log('request - 2', teachers);
    });
    this.request().subscribe((teachers: Array<Teacher>) => {
      console.log('request - 3', teachers);
    });
  }

  request(): Observable<Array<Teacher>> {
    return this.httpClient.get<Array<Teacher>>('/assets/mock/teacher.json');
  }
}

三个调用方都拿到了数据:spa

image.png

同一个接口,发起了三次HTTP请求:设计

image.png

初代版本

流程以下:code

image.png

自定义一个观察者对象,全部要获取当前登陆用户的组件要去currentLoginUser$观察者上进行订阅。

系统初始化时,请求接口数据,将结果next进观察者对象中。

  • 确实解决了屡次请求的问题。
  • 由于初始化时请求,因此当数据变动时,再订阅到的数据仍是旧数据。
  • 思惟困难,须要实现者深刻理解观察者模式。

迭代

最新在StackOverflow上发现能够采用RxJS share方式完美地解决该问题,以下所示:

定义一个观察者对象teachers$,可是这个对象不须要咱们本身维护,咱们只须要调用httpClient的方法,将它返回的可观察对象使用share操做符过滤便可。

以后改造request方法,返回teachers$可观察对象。

export class AppComponent implements OnInit {

  teachers$: Observable<Array<Teacher>>;

  constructor(private httpClient: HttpClient) {
    this.teachers$ = this.httpClient.get<Array<Teacher>>('/assets/mock/teacher.json').pipe(share());
  }

  ngOnInit(): void {
    this.getTeachers();
  }

  getTeachers(): void {
    this.request().subscribe((teachers: Array<Teacher>) => {
      console.log('request - 1', teachers);
    });
    this.request().subscribe((teachers: Array<Teacher>) => {
      console.log('request - 2', teachers);
    });
    this.request().subscribe((teachers: Array<Teacher>) => {
      console.log('request - 3', teachers);
    });
  }

  request(): Observable<Array<Teacher>> {
    return this.teachers$;
  }
}

三个调用方都拿到了数据:

image.png

同一个接口,只发起了一次HTTP请求,节省了网络资源:

image.png

  • 一样实现HTTP复用功能。
  • 使用方法简单,都是模板代码,即使初学者也可按照范例进行编写。

share

RxJS至关复杂,这里的share也只是它的冰山一角。

share运算符不太好理解,RxJS相关的概念太多,这里就不一一展开了,请参考文章:译 RxJS: 理解 publish 和 share 操做符

固然,若是你没有足够地时间去学习探究share运算符,就大胆地使用上述示例代码吧,这,就是最佳实践。

总结

RxJS基于观察者,但不止于观察者,RxJS存在着众多的操做符,且都不是那么好理解,太伟大了。

相关文章
相关标签/搜索