RxJS的学习之路一(RxJS初探)

2,518 阅读4分钟

引言

作为前端小白,在进入第一个公司后的项目用的框架就是三大框架中最难的angular4,在折腾完angular的语法和typeScript后开始写一些业务代码,发现angular的项目中有大量RxJS的内容,在异步请求,状态管理,服务管理等等方面都有应用。而这个东西又实在折腾人,官方文档上面写的晦涩又抽象,网上的中文资料也很少,还有很多是老版本的东西,看的一脸懵逼。

在踩了许多坑之后决定将自己的学习过程用博客记录下来,希望可以加深记忆,也希望能对新学RxJS的人有些许帮助

文章参考

文章参考了很多网上的资料及自身的学习过程

RxJS中文文档

it邦铁人赛,JerryHong大佬的30天精通RxJS系列(强烈推荐)

RxJS简单入门

RxJS是什么

RxJS是一个异步编程的库,同时它通过observable序列来实现基于事件的编程,它使编写异步或基于回调的代码更容易。

RxJS的优势

这个问题百度下都能有答案,在我看来,RxJS的最大优势就在于两点:

  • 代码量的大幅度减少
  • 代码可读性的提高

文字的叙述实在抽象,我就从工作中遇到的第一RxJS的案例来说明。

我遇到的需求是angular中表单的异步校验功能,需要验证输入表单中的名称后台是否存在,angular中表单存在异步校验器,异步校验器需要你输出一个观察者对象,监听输入事件,并返回检验结果。

按照以前的思维模式,我们完成这个校验器的思路应该是:

1. 监听键盘事件或者input的valueChange事件

2.将触发的事件进行,防抖,去重处理

3. 发送请求到后台获取当前的名称库(因为数量不大,所以验证由前端进行)

4. 检查是否存在

写出来代码就是这样

  nameValidator = (control: FormControl) => Observable.create((observer: Observer<ValidationErrors>) => {
    let timer: any; 
    // 监听valuechange事件
    control.valueChanges().subscribe(name => {
      clearTimeout(timer)
      // 定义400毫秒延时器来防抖
      timer = setTimeout(() => {  
        this._serv.getAnalysisDetail(this.analysisId).subscribe(res => {
          const valueSet = res.data.instanceList;
          // 检查名称是否存在并返回校验结果
          if (valueSet.find(item => item.name === name)) {
            observer.next({ nameValidator: true })  // 名称存在
          } else {
            observer.next(null)  // 名称不存在
          }
          observer.complete();
        })
      }, 400);
    })
  });

这样的写法也是antd中异步校验器的例子的写法,也是我当时接到需求提交的代码,在同事review之后,他用RxJS直接重构了这个函数,代码量大幅减少,可读性也增加了

 nameValidator = (control: FormControl) => this.instanceLen ? control.valueChanges.pipe(
    debounceTime(400), // 防抖
    switchMap(
      name => zip(this._serv.getAnalysisDetail(this.analysisId), of(name)) // 将名称和请求结果合并输出
    ),
    map(([res, name]: any[]) => {
    // 检查并返回结果
      const nameCheck = res.data.instanceList ? !!res.data.instanceList.find(item => item.name === name) : false;
      return nameCheck ? control.setErrors({ nameValidator: true }) : control.setErrors(null);
    })
  ) : of(null)

RxJS将思路完全转化为了一种‘流式编程’的思想

  • 获取valuechange事件最为事件流,并放到管道(pipe)中
  • debouceTime为管道中第一道处理,是RxJS内置的防抖接口
  • switchMap将流过来的数据和另外一个流(异步请求)合并,两两输出
  • 输出的结果在map函数中进行结果处理

RxJS将各种繁杂的回调函数用事件流的方式展现出来,只要你知道相应的语法和api,不用注释也能清楚这个流程,代码可读性大大增加。

RxJS要学些什么

官网上列了六个需要学习的内容,而我从实际应用中,常用和必须掌握的是这四点

  • Observable:代表了一个调用未来值或事件的集合的概念
  • Observer:代表了一个知道如何监听Observable传递过来的值的回调集合
  • Operators:是一个纯函数,允许处理集合与函数式编程风格的操作,比如map、filter、concat、flatMap等
  • Subject:相当于一个EventEmitter,它的唯一的方法是广播一个值或事件给多个Observer

而这其中最重要的就是obserable的理解和subject的理解使用。

我计划在之后的几篇文章中,对RxJS的这些方面进行一遍梳理,并且探究它在状态管理等其他方面的应用,希望对自己,对新学习RxJS的人能有所帮助,大家都能写出优雅简洁的代码。