RxJS學(xué)習(xí)筆記(1)

RxJS

概述

RxJS全名Reactive Extensions for JavaScript,起源于Reactive Extensions項目,該項目主要實現(xiàn)各種語言的響應(yīng)式編程(Reactive programming)庫,被認(rèn)為是觀察者模式與函數(shù)式編程相結(jié)合的最佳實踐。官方是這樣吹噓的:

Reactive Revolution:ReactiveX is more than an API, it's an idea and a breakthrough in programming. It has inspired several other APIs, frameworks, and even programming languages.

而RxJS是其項目中一個基于JavaScript的庫,主要用于解決js中的異步編程問題。說到這里,我們又不得不提一下響應(yīng)式編程的思想,其主要思路如下:

響應(yīng)式的思路:是把隨時間不斷變化的數(shù)據(jù)、狀態(tài)、事件等等轉(zhuǎn)成可被觀察的序列(Observable Sequence),然后訂閱序列中那些Observable對象的變化,一旦變化,就會執(zhí)行事先安排好的各種轉(zhuǎn)換和操作。

RxJS是比ES7中async/await更高層面的流程邏輯抽象,把異步帶來的時間因素給剝離到了程序流程外部,描述了一個動態(tài)的數(shù)據(jù)結(jié)構(gòu)(數(shù)據(jù)流,stream)。因為我們平時寫代碼時都是關(guān)注程序執(zhí)行的瞬間,即靜止?fàn)顟B(tài),缺少了時間這個維度。所以RxJS就給我們提供了很多與時間無關(guān)的通用高層抽象,即數(shù)據(jù)流操作算符api。通過這些api,我們可以自由地定義數(shù)據(jù)流的過濾、轉(zhuǎn)換和組合等操作的組合關(guān)系,而無需關(guān)心具體操作的實現(xiàn)。

好處

  1. 事件產(chǎn)生邏輯與處理邏輯分離

  2. 事件處理邏輯被數(shù)據(jù)結(jié)構(gòu)化,能自由組合,方便修改擴(kuò)展(函數(shù)式編程的思想)

Why RxJS

RxJS是最近幾年興起的,關(guān)注度還是挺高的(github上有18000+star)。但是其理念還是比較抽象的,所以學(xué)習(xí)成本還是有點大的。

那么為什么還是要學(xué)呢?

因為最近項目框架轉(zhuǎn)型,由angularjs轉(zhuǎn)向angular2+,這次Google和微軟聯(lián)手,angular和typescript打包,也就順帶引入了小弟RxJS(捂臉)。

不過,引入RxJS也存在著一個問題,就像知乎上說的:

Rx 的一個問題就是它其實是一個 paradigm,侵入性很強(qiáng)。你如果要用 Rx 寫東西,最好就整個系統(tǒng)都是以 Rx 為核心來設(shè)計。

如何過渡到RxJS

這里主要以angularjs過渡到angular中使用RxJS為例。

普通的Promise

對于一個普通的promise,我們一般處理如下:

promise().then(
  ()=>{
    // success
  },
  ()=>{
    // error
  });

而在RxJS中,我們一般得到的是一個Observable(可觀察對象),類似的像上面一樣的處理被稱為訂閱,其實現(xiàn)如下:

observable().subscribe(
  ()=>{
    // next
  },
  ()=>{
    // error
  },
  ()=>{
    // complete
  });

這里的next就相當(dāng)于success,但又不同。因為Observable(可觀察對象)是基于推送(Push)運(yùn)行時執(zhí)行(lazy)的多值集合,所以對一個Observable的訂閱可能產(chǎn)生多個next。不過對于一般的http請求,只會產(chǎn)生一個next。不過,兩者的error基本相同。但是,這里需要注意的是,complete只會在next執(zhí)行完成后調(diào)用,error時不調(diào)用。大致邏輯如下:

const observable = Observable.create(function (observer) {
      try {
        observer.next(1);
        observer.next(2);
        observer.next(3);
        observer.complete();
      } catch (err) {
        observer.throw(new Error(err));
      }
    });

并發(fā)promise

在應(yīng)用場景中,我們可能需要同時發(fā)送多個請求,并且成功后才進(jìn)行處理。

Promise中提供了all()方法,接收參數(shù)為一個可迭代對象,使用如下:

const promise = Promise.all([promiseA, promiseB, promiseC]);
promise().then(
  ()=>{
    // success
  },
  ()=>{
    // error
  });

類似的,angularjs中提供了$q.all()。

而在RxJS中,也提供了相應(yīng)的操作算符api,即Observable.forkJoin(),用法與上面類似:

const observable = Observable.forkJoin(observableA, observableB, observableC);
observable().subscribe(
  ()=>{
    // next
  },
  ()=>{
    // error
  });

需要注意的是,RxJS5以后,這種算符的使用都需要加上相應(yīng)的引用,如這里需要加上import 'rxjs/add/observable/forkJoin'

串行promise

考慮另一種場景,請求B調(diào)用依賴請求A成功后返回的數(shù)據(jù)。

在Promise中我們通常如下處理:

promiseA.then(
  data=>{
    // promiseA success
    return promiseB(data);
  },
  ()=>{
    // error
  }).then(
    ()=>{
      // promiseB success
    },
    ()=>{
      // error
    });

類似的,RxJS中也提供了相應(yīng)的api,即Observable.mergeMap(),用法如下:

observableA.mergeMap(
  data=>{
    // observableA next
    return observableB(data);
  }).subscribe(
    data=>{
      // observableB next
    },
    ()=>{
      // error
    });

改造promise

為了方便向使用RxJS庫的過渡,RxJS中還提供了toPromise()、fromPromise()方法,方便進(jìn)行Observable對象與Promise對象之間的相互轉(zhuǎn)換。

To be continue

當(dāng)然RxJS的功能還遠(yuǎn)不止這些,持續(xù)更新中...如果有什么問題,歡迎小伙伴們一起討論,大家一起共同進(jìn)步=。=

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容