1. 介紹
RxJS 是什麼?用一句話類概括就是:RxJS 是用于 JavaScript 的ReactiveX 庫,它是一個可以通過觀察序列變化,掌握非同步事件處理的利器。
在學習 RxJS 之前我們首先需要了解以下的前提知識:
-
Reactive Extensions(Rx)
是一個使用可觀察序列和 LINQ 樣式查詢運算符組成異步和基于事件的程式的庫。
-
ReactiveX
是 observer 模式、lterator 模式和函數式程式設計的最佳思想的組合。
-
Reactive Programming(反應式程式設計)
是用異步資料流程式設計。
-
Streams
流——便宜又無處不在,什麼都可以是一股流。比如變量、使用者輸入、屬性、緩存、資料結構都可以被稱為流。
舉一個程式化的例子來說,假如現在有一個觀察者訂閱了 click 事件,當有使用者在頁面上點選滑鼠時,每一次點選都會觸發一次 click 事件,并發送 click 事件資料(Mouse Event)給觀察者,當使用者連續點選多次,觀察者就會收到一系列的事件資料,我們把這一系列的事件資料就叫做一個流(Stream)。
再舉一個非同步事件的例子,我們通過某非同步事件,向服務端發送 Ajax 請求,然後從服務端得到響應資料,在這個過程中,可能會持續地發出多個 Ajax 請求,并且響應資料會不同時間、不同順序地傳回用戶端。類似這樣的過程,就是串流的概念。
在非同步事件中,由于事件響應的時間不确定、順序不确定,JavaScript 在處理非同步事件時,會有一定的困難,很容易出現 bug,而 RxJS 可以輕松幫我們處理這樣的非同步事件。
總結來說,使用 RxJS 的目的就是,有效管理非同步環境下的事件資料。
我們知道 RxJS 是一組可用來處理非同步或事件的 JavaScript 函式庫,那麼非同步或事件的種類有哪些呢?
-
非同步
Ajax/XHR/fetch API
Service Worker/Node Stream
setTimeout/setInterval
Promise
-
事件
各種 Dom 事件(click/dbclick/keyup/mousemove……)
CSS 動畫事件(CSS3 transitionEnd event)
HTML5 Geolocation/WebSockets……
2. 核心概念
-
Observable 可觀察的物件
代表一組未來即将産生的事件資料(被觀察的物件)。從上面舉的例子中來說,click 事件就是一個 Observable,也就是說當 click 事件被觸發的時候,它會發出一些事件資料(Stream)給觀察者。
-
Observer 觀察者
代表一個用來接收觀察結果的物件(Observer 收到的就是事件資料,也就是 Stream)。
-
Subscription 訂閱
表示 Observable 的執行,主要用于取消訂閱。
-
Operator 運算符
用來處理一系列的事件資料集合,可以了解成 Operator 會通過一系列的過濾、篩選等操作,對 Observable 進行處理,最終将事件資料送給觀察者。
常見的運算符包括:map/filter/concat/flatMap……
-
Subject 主體物件
主要用來廣播收到的事件資料給多位 Observer。
-
Scheduler 排程控制器
用來集中管理和排程多重事件之間的資料,以控制事件并發情況。
3. 基本運作過程

上面這段代碼的意思是,通過 RxJS 去使用建立運算符(Creation)的 API(interval) 建立一個 Observable,這個 Observable 會每 0.5s 發出一個數字(從 0 開始)。然後通過 pipe(中文是水管的意思,可以結合流的概念來了解)中的過濾運算符 take ,隻發送前四筆資料給觀察者。觀察者(console.log)通過 subscribe 去訂閱到 Observable 發送的資料。
上面的代碼運作結果如下:
在上面提到的核心概念中,有提到 Subscription 這一概念,在這裡可以舉個例子幫助我們加深了解。現在我們将上面代碼中通過 take 方法隻取前 4 筆資料,改為取前 40 筆資料,并且将觀察結果存在 subs 中,這裡的 subs 也就是我們所說的 Subscription。最後在通過 subs 調用 unsubscribe 方法取消觀察者和可觀察物件的訂閱關系,也即不再接受可觀察物件發來的訂閱資料。
上邊那段代碼還可以利用 ES5 解構指派來精簡一下寫法:
也可以通過 ES Module 來精簡代碼:
上面是 RxJS 基本的運作過程,那代碼怎麼寫呢?
- 建立可觀察的 Observable 物件
- 建立觀察者 Observer 物件
- 建立訂閱物件(訂閱 Observable 物件,并傳入 Observer 觀察者物件)
- 取消訂閱 Subscription 物件
上面的代碼運作結果就是,每當在頁面 document 範圍内點選滑鼠時,控制台就會列印一次 MouseEvent 事件。這裡需要注意一點的是,必須有觀察者訂閱 Observable,Observable 發生的事件才會被觸發,沒有訂閱的觀察者,Observable 就不會産生任何事件資料。
上面是語義清晰的一種寫法,下面是一種簡易的寫法:
- 建立可觀察的 Observable 物件
- 建立訂閱物件(訂閱 Observable 物件,并自動建立觀察者物件)
- 取消訂閱 Subscription 物件
4. RxJS 如何通過運算符過濾資料
現在我想要訂閱 click 事件,并且傳回 ClientX 小于 1000 的所有事件,代碼如下:
- 建立可觀察的 Observable 物件
- 套用 filter 運算符
const { filter } = rxjs.operators; clicks$ = clicks$.pipe(filter(x => x.clientX <1000));
- 建立訂閱物件(訂閱 Observable 物件,并自動建立觀察者物件)
- 取消訂閱 Subscription 物件
假如現在我隻需要傳回 ClientX 小于 1000 的所有事件中的前四筆資料,我們需要對運算符部分的操作進行更改:
var subs = clicks$.pipe(
filter(x => x.clientX <1000),
take(4)
).subscribe((x) => console.log(x));
這裡需要注意的是,隻有符合條件的資料流能夠被列印出來,并且一但 take 運算符一旦收集夠四個事件之後,就會自動執行取消訂閱的操作。
5. RxJS 主體物件(Subject)的用法
- 建立主體物件(Subject,之後要靠這個主體物件進行廣播)
- 建立可觀察的 Observable 物件
- 設定最多取得兩個事件資料就将 Observable 物件設為完成
- 設定将 clicks$ 全部交由 subject 主體物件進行廣播
- 最後再由 subject 去建立 Observer 觀察者物件
var subs1$ = subject.subscribe((x) => console.log(x.clientX)); var subs2$ = subject.subscribe((x) => console.log(x.clientX));
- 取消訂閱 Subscription 物件
subs1$.unsubscribe(); subs2$.unsubscribe();
通過 Subscription 事件資料隻需要發送一次給 subject 就完成了,而不需要分别發送兩次給 subs1$ 和 subs2$。
6. 彈珠圖
彈珠圖可以很好的描述 RxJS 中操作運算符的運算過程。
- take
RxJS新手入門1. 介紹2. 核心概念3. 基本運作過程4. RxJS 如何通過運算符過濾資料5. RxJS 主體物件(Subject)的用法6. 彈珠圖7. 如何選擇運算符 - map
RxJS新手入門1. 介紹2. 核心概念3. 基本運作過程4. RxJS 如何通過運算符過濾資料5. RxJS 主體物件(Subject)的用法6. 彈珠圖7. 如何選擇運算符 - concat
RxJS新手入門1. 介紹2. 核心概念3. 基本運作過程4. RxJS 如何通過運算符過濾資料5. RxJS 主體物件(Subject)的用法6. 彈珠圖7. 如何選擇運算符
在這個網站可以看到更多彈珠圖。
在這個網站還可以看到以動畫呈現的彈珠圖
7. 如何選擇運算符
RxJS 的運算符衆多,有時候不知道選擇哪一個更有效,這時候可以在這個網站通過互動式的問答,選擇出合适的運算符。
運算符的分類:
本篇文章整理自b站視訊一小時 RxJS 入門