學習 RXJS 系列(一)——從幾個設計模式開始聊起
一、RXJS 是什麼
RXJS
是 Reactive Extensions for JavaScript
的縮寫,起源於 Reactive Extensions
,是一個基於可觀測數據流 Stream
結合觀察者模式和迭代器模式的一種異步編程的應用庫。RxJS
是 Reactive
Extensions
在 JavaScript
上的實現。
二、前置知識
響應式編程
響應式編程(Reactive Programming
)是一種基於事件的模型,它是一種面向數據流和變化傳播的編程範式。這意味着可以在編程語言中很方便地表達靜態或動態的數據流,而相關的計算模型會自動將變化的值通過數據流進行傳播。例如,對於 a=b+c
這個表達式的處理,在命令式編程中,會先計算 b+c
的結果,再把此結果賦值給 變量 a,因此 b,c 兩值的變化不會對 變量 a 產生影響。但在響應式編程中,變量 a 的值會隨時跟隨 b,c 的變化而變化。
響應式編程的思路大概如下:你可以用包括 Click
和 Hover
事件在內的任何東西創建 Data stream
。任何東西都可以是一個 Stream
:變量、用戶輸入、屬性、Cache
、數據結構等等。
流
概括來說,流的本質是一個按時間順序排列的進行中事件的序列集合。我們可以對一個或多個流進行過濾、轉換等操作。需要注意的是,流是不可改變的,所以對流進行操作後會在原來的基礎上返回一個新的流。
觀察者模式
觀察者模式(有時又被稱爲模型(Model)- 視圖(View)模式、源 - 收聽者 (Listener) 模式或從屬者模式)是軟件設計模式的一種。在此種模式中,一個目標物件管理所有相依於它的觀察者物件,並且在它本身的狀態改變時主動發出通知。這通常透過呼叫各觀察者所提供的方法來實現。此種模式通常被用來實現事件處理系統。
觀察者模式(Observer)完美的將觀察者和被觀察的對象分離開。舉個例子,用戶界面可以作爲一個觀察者,業務數據是被觀察者,用戶界面觀察業務數據的變化,發現數據變化後,就顯示在界面上。看到上面這個描述的場景是不是覺得似曾相識?Vue 的工作原理不就是這樣的嗎,將數據與視圖雙向綁定,通過響應式編程的思想動態更新訂閱的觀察者列表。
迭代器模式
迭代器模式(Iterator Pattern)是一種非常常用的設計模式。這種模式用於順序訪問集合對象的元素,不需要知道集合對象的底層表示。迭代器模式屬於行爲型模式。
JavaScript 中 原有表示 “集合” 的數據結構主要是 “數組 (Array)” 和 “對象 (Object)”,ES6 又新增了 Map
和 Set
,共四種數據集合,瀏覽器端還有 NodeList
類數組結構。ES6 中也有 Iterator 迭代器的介紹,爲 “集合” 型數據尋求統一的遍歷接口正是 ES6 的 Iterator 誕生的背景。
三、基本概念介紹
Observable
Observable
表示一個可調用的未來值或事件的集合,他能被多個 observer
訂閱,每個訂閱關係相互獨立、互不影響。這裏可以舉個簡單的例子,假如你訂閱了報紙,只要報紙每次有新的內容出來就會送到(更新)你手上,這個場景中報紙就是 Observable,而你就是一個觀察者(observer)。
我們看看在 RXJS 中怎麼創建一個 Observable:
const Rx = require('rxjs/Rx');
const newObservable = Rx.Observable.create(observer => {
observer.next('message1');
});
這裏通過調用 Observable.create
創建了一個 Observable
,這個方法接受一個函數作爲參數,這個函數叫做 producer
函數, 用來生成 Observable
的值。這個函數的入參是 observer
,在函數內部通過調用 observer.next()
便可生成有一系列值的一個 Observable
。
Observer
Observer 是一個回調函數的集合,也就是一個包含幾個回調函數的對象。它知道如何去監聽由 Observable
提供的值。Observer
在信號流中是一個觀察者(哨兵)的角色,它負責觀察任務執行的狀態並向流中發射信號。
我們簡單描述下一個 Observer 長什麼樣子:
const observer = {
next: function(value) {
console.log(value);
},
error: function(error) {
console.log(error);
},
complete: function() {
console.log('complete');
}
}
RXJS 中 Observer 的回調函數是可選的,我們定義 Observer 時可以不定義 next、error 或者 complete,這並不會對 Observer 的執行造成影響。
我們來看下如何定義一個 Observer:
const newObservable = Rx.Observable.create((observer) => {
observer.next('message1');
})
newObservable.subscribe((text) =>console.log(text));
這裏通過 subscribe
方法讓一個 observer
訂閱一個 Observable
。你可能對 subscribe
的參數有些疑惑,這裏我們可以看看 subscribe
的函數定義,瞭解是如何與上面我們提到的 next、error 和 complete 關聯起來的:
subscribe(next?: (value: T) =>void, error?: (error: any) =>void, complete?: () =>void): Subscription;
從入參來看,從左至右依次是 next
、error
,complete
,並且是可選的,我們可以自己選擇性的傳入相關回調,因爲他們都是可選的。
Subscription
Subscription
表示 Observable
的執行,我們可以調用該對象的 unsubscribe
方法清理掉 Observable
的執行,這個方法不需要任何參數,只是用來清理由 Subscription
佔用的資源。
const myObservable = Rx.Observable.create(observer => {
observer.next('foo');
setTimeout(() => observer.next('bar'), 1000);
});
const subscription = myObservable.subscribe(x =>console.log(x));
subscription.unsubscribe();
我們可以看到,Observable
的執行需要調用 subscribe
方法來觸發,如果在 Observable
執行的時候我們調用了 unsubscribe
方法,就會取消正在進行中的 Observable
的執行。
Subject
Subject 對象可以當成是一箇中間代理,它位於 Observable 和 Observer 中間,相對於 Observable 來說它是一個 Observer,接收 Observable 發出的數據;相對於 Observer 它又是一個 Observable,對訂閱了它的 observer 發送數據。
需要注意的是,Subject 會對訂閱了它的 observers 進行多播,這裏就涉及到一個單播與多播的概念了,我們分析一下這兩個概念:
單播:單播的意思是,每個普通的 Observables
實例都只能被一個觀察者訂閱,當它被其他觀察者訂閱的時候會產生一個新的實例。也就是普通 Observables
被不同的觀察者訂閱的時候,會有多個實例,不管觀察者是從何時開始訂閱,每個實例都是從頭開始把值發給對應的觀察者。
多播:前面說到,每個普通的 Observables
實例都只能被一個觀察者訂閱,但是如果通過 Subject 來代理 Observable 實例的話就能夠被多個 observer 所訂閱,且無論有沒有 observer 訂閱,都會發送數據。也就是說無論 observer 什麼時候訂閱都只會接收到實時的數據。
四、參考文章
-
RxJS—— 給你如絲一般順滑的編程體驗
-
RXJS 中文文檔
下一篇文章中我們繼續介紹一下幾種不同類型的 Subject 以及 Cold/Hot Observables,希望能對大家有所幫助。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/tlFb4NHcdr5Ej8kxzfO88w