數據驅動(data-driven
) 是指將傳遞的數據和行為進行分離。這也是為什么RxJS能夠以相同的范式來處理不同類型的數據源(比如數組,字符串,事件,AJAX請求等等)的核心原理。
- 以數據作為中心,將數據從行為系統中分離出來,用數據去驅動業務
- 沒有數據,行為將不起作用,數據給行為帶來升級,行為響應數據的變化,而不是等待數據的到來
- 流(stream)只是一個傳遞過程,如果沒有用戶訂閱,或者數據傳遞進來,流將保存閑置狀態
數據生產者 producers
數據的產生有不同的原因,這樣造成數據源的來源有很多種情況。
- 生產者有各種各樣的形態和大小,
Event Emitter
就是比較常見的一種生產者,它們用于響應鼠標點擊或者網絡請求,同時他們也是基于時間的數據源 - 當處理不同類型的數據源,我們應當自然會想到使用不同類型的方式來處理。不如
event emitters
需要使用命名event handlers 來處理,Promises
需要一個連續傳遞的thenable
函數來處理;setTimeout
需要回調函數來處理;Arrays
需要通過循環來迭代數據
但是Rx對不同類型的數據進行了包裝處理,這樣我們可以以相同的范式來處理不同類型的數據源,也就是說
不同類型的數據源在事件驅動(或流驅動)的棱鏡下觀察都是一樣的,
就好比Rx.Observable 是一個錘子,把其余所有的數據類型當作釘子
識別不同類型的數據源
數據源廣義的可以分為以下幾類:
- Emitted Data
- Static Data
- Generated Data
1.Emitted Data
發生數據是一種外部與系統交互產生的結果。可以來自與用戶交互,比如點擊鼠標,也可以是系統事件,比如讀取文件。
比如你請求數據,未來某個時間點,你接收到數據,對于這種情況, Promises
可能是一個好的解決方案。
2.static data
靜態數據已經存在或者顯示在系統(內存)中,比如 array
,string
。人工的單元測試數據就劃分到這一類型數據中。
3.Generated data
產生的數據是指間隔的或最終產生的數據,比如時鐘每小時都會報時。
比如無限產生的數據,不可能將其全部存儲在內存中,值應當動態的被創建和產生給需要的使用者。
數據類型的劃分
根據以下2個維度可以將數據劃分為4類:
- 值的多少: 單值(比如數字), 多值(比如數組)
- 數據的處理方式: 同步的, 還是異步的
1.single-value && synchronous
這是最簡單的數據類型,比如數字,一個對象,我們可以通過 Rx.Observable.of
將其轉換為一個 Obserable類型。
但是一般處理簡單類型的數據使用Observable,有點殺雞用牛刀的味道,一般只有我們希望將簡單類型的值和其它類型的流整合在一起時,才使用Obserable
2.multi-value && synchronous
我們可以將單值集合起來形成集合,主要是數組類型。
我們可以使用 Rx.Obserable.from
將集合類型轉換為Obserable類型
3.single-value && asynchronous
對于異步的情況,正是RxJS大放異彩的地方。
對于異步的情況,我們只能保證到嗎在未來某個時間被處理,因此,后面的代碼塊不能依賴前面代碼塊的執行。
對于單值異步的情況,使用 Promises
進行處理最好了,在RxJS中可以使用 Rx.Observable.fromPromise()
將promises轉換為Observable類型。
Rx.Observable.fromPromise($.ajax('/data'))
4. multi-value && aynchronous
這種類型的數據一般時間會作為數據來源的因子。比如DOM事件,不知道未來什么時候會產生。
對這種數據的處理我們需要 混合迭代器和promise模式,通常的處理方式是使用 EventEmitter
進行處理。
RxJS在javascript原有的EventEmitter的基礎上對其進行了改進。可以使用 Rx.Observable.fromEvent()
將EventEmitter 轉換為Observbale類型
PUSH-BASED && PULL-BASE MODEL
迭代器使用的 pull-based
模型, 而RXJS使用的是 push-based
模型。
-
pull-based
對下面情況是非常擁有的: 當我們知道一個字能從計算后立即返回時。對于不知道值什么時候返回或者有沒有值返回的情形,pull-based
模型就失效了,比如鼠標點擊,使用者是不知道下一次點擊事件什么時候反生,或者發不發生 -
push-based
模式中,生產者負責創建下一個數據,消費者只需要監聽新的事件即可
Observable && Observer
被觀察者和觀察者
- 業務邏輯,比如值如何產生,怎么被發送歸屬于Observable,而所有的渲染細節,是否使用插件什么的處理邏輯歸屬于observer中的調度者
- 要記住,無限事件發送,比如DO事件,將不會觸發 complete() 方法,因此,取消訂閱取決于使用者,可以采取手動取消訂閱或者自動取消訂閱機制
Observable 基本api
被觀察者本質上一個函數
下面用簡單的方式來描述observable
const observable = events => { // 時間隊列
const INTERVAL = 1 * 1000;
let schedulerid;
return { // 返回一個包含 'subscribe' 方法的對象
subscribe: oberver => { // 接收 observer 對象作為參數
schedulerid = setInterval(() => {
if (events.length === 0) { // 如果沒有時間處理了
observer.complete();
clearInterval(schedulerid);
schedulerid = undefined;
} else { // 如果有事件反生, 使用 observer.next()方法進行處理
observer.next(events.shift());
}
}, INTERVAL);
return {
unsubscribe: () => { // subscribe 方法返回一個unsubscribe 方法用于取消訂閱
if (schedulerid) {
clearInterval(schedulerid);
}
}
};
}
}
}
總結
主要將了以下幾個方面
- RxJS采用了數據驅動的方式,數據和業務邏輯分離
- RxJs對javascript的EventEmitter進行了改進,使其可以對事件進行推送
- Push-based 和 Pull-based 方式的差異
- 根據值的多少和處理方式2個維度,將數據源劃分為4類
- 簡單Observable apis的介紹
- Rx.Observable.of()
- Rx.Observable.from()
- Rx.Observable.fromPromise()
- Rx.Observable.fromEvent()
- Observable 和 Observer 之間的關系簡單介紹