RxJS的學習之路一(RxJS初探)

elc發表於2019-02-18

引言

作為前端小白,在進入第一個公司後的專案用的框架就是三大框架中最難的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的人能有所幫助,大家都能寫出優雅簡潔的程式碼。

相關文章