什麼是Rx.JS?
Rx.JS
是英文 Reactive Extensions for JavaScript 的縮寫.翻譯成中文就是:JavaScript的響應式擴充套件.其主要的功能就是利用響應式程式設計的模式來實現JavaScript的非同步式程式設計.
相對於JavaScript中其它的非同步式解決方式(回撥函式、Promise、Gender、async函式而言),Rx.JS有著更加強大的特性和更加優雅的寫法.如(純淨性、流動性、值)。
Rx.JS的基本概念
Rx.JS的響應式程式設計操作是結合了觀察者模式、迭代模式以及函數語言程式設計來實現的.它主要有著如下幾個概念:
- Observable (可觀察物件): 表示一個概念,這個概念是一個可呼叫的未來值或事件的集合。
- Observer (觀察者): 一個回撥函式的集合,它知道如何去監聽由 Observable 提供的值。
- Subscription (訂閱): 表示 Observable 的執行,主要用於取消 Observable 的執行。
- Operators (操作符): 採用函數語言程式設計風格的純函式 (pure function),使用像 map、filter、concat、flatMap 等這樣的操作符來處理集合。
- Subject (主體): 相當於 EventEmitter,並且是將值或事件多路推送給多個 Observer 的唯一方式。
- Schedulers (排程器): 用來控制併發並且是中央集權的排程員,允許我們在發生計算時進行協調,例如 setTimeout 或 requestAnimationFrame 或其他。
下面,來讓我們看一個簡單的示例.
我們都知道,在前端開發當中為效能的優化,我們往往會對某個持續不斷會觸發的事件做一下事件節流.,也就是事件增加一個節流閥
,以限制事件的不斷觸發.最常見的做法就是設定一個定時器.來進行判斷.事件在多少秒之內不斷觸發的話.就將節流閥
開啟.不進行事件操作.直達不斷觸發事件的行為結束之後,才進行事件操作.最常見的就是輸入框的例子.如下面程式碼所示:
<input id="text"></input>
<script>
var text = document.querySelector('#text'),
timer = null,
currentSearch = '';
text.addEventListener('keyup', (e) =>{
clearTimeout(timer)
timer = setTimeout(() => {
// 宣告一個當前所搜的狀態變數
currentSearch = '書';
var searchText = e.target.value;
$.ajax({
url: `search.qq.com/${searchText}`,
success: data => {
// 判斷後臺返回的標誌與我們存的當前搜尋變數是否一致
if (data.search === currentSearch) {
// 渲染展示
render(data);
} else {
// ..
}
}
});
},250)
})
</script>複製程式碼
上面的程式碼就是一個很常見的一個事件節流的用法.當你按下鍵盤觸發事件時,並不是直接傳送AJAX請求.而是使用setTimeout
延遲250毫秒.在延遲的過程中如果有新的事件觸發.就會重新計算延遲.如此不斷的反覆.直到兩次觸發事件的間隔大於250毫秒.才會真正的傳送AJAX請求.
下面讓我們來看看上述的邏輯用RxJS怎樣的實現.
var button = document.querySelector('button');
Rx.Observable.fromEvent(button, 'click')
.debounceTime(250)
.subscribe(function(){
$.ajax({
url: `search.qq.com/${searchText}`,
success: data => {
// 判斷後臺返回的標誌與我們存的當前搜尋變數是否一致
if (data.search === currentSearch) {
// 渲染展示
render(data);
} else {
// ..
}
}
});
});複製程式碼
上面是用RxJS實現的同樣的功能.但我們看到其程式碼精簡了許多.上述程式碼中首先獲取到一個button
元素.然後使用Rx.Observable.fromEvent
建立了一個被觀察物件.其物件所監聽的是button
元素的.click
事件.每當button
元素的click
事件觸發時.就會發射一個值出去.這個值途中經過debounceTime
操作符,延時了250毫秒.然後再被觀察者物件捕獲.最終觸發其定義的AJAX事件.這就是上述程式碼中的實現過程.
然而我們看到.雖然上述在定義執行的過程中做了許多的事情,但這些是RxJS在內部幫助我們就做好了的.我們只需要它給我們的API方法就可以實現用幾段簡單的程式碼,實現一段複雜的操作.
Observable (可觀察物件)
Observables 是多個值的惰性推送集合
Observable是RxJS的核心概念之一.它實際上就是可以被外界觀察的一個物件.當本身的狀態發生變化時,就會將其變化推送給外界觀察它的物件,也就是 觀察者物件.同時因為Observables 是多個值的惰性推送集合
所以只有當使用一個觀察者物件去訂閱了它之後.它才會同步或非同步地返回零到(有可能的)無限多個值.下面是使用RxJS建立一個Observable
的方式
var observable = Rx.Observable.create(function subscribe(observer) {
var id = setInterval(() => {
observer.next('hi')
}, 1000);
});複製程式碼
上面例項建立了一個 Observable,它每隔一秒會向觀察者傳送字串 'hi'.
Observer (觀察者)
什麼是觀察者? - 觀察者是由 Observable 傳送的值的消費者。觀察者只是一組回撥函式的集合,每個回撥函式對應一種 Observable 傳送的通知型別:next、error 和 complete 。
簡單來說,Observer
就是使用Observable
傳送出來值的一個方法集合.當一個Observable
傳送出來值之後由Observer
來決定如何的去使用它.而使用的方式就是通過回撥函式.將Observable
傳送出來的值作為引數傳入其中.讓後在內部去使用.同時根據Observable
傳送出來的值不同.其呼叫的回撥函式也不同.分別有next
(下一步),error
(報錯),complete
(結束).下面是使用Observer
的方法:
observable.subscribe(observer);複製程式碼
要使用觀察者,需要把它提供給 Observable 的 subscribe 方法
Subscription (訂閱)
什麼是 Subscription ? - Subscription 是表示可清理資源的物件,通常是 Observable 的執行。Subscription 有一個重要的方法,即 unsubscribe,它不需要任何引數,只是用來清理由 Subscription 佔用的資源。在上一個版本的 RxJS 中,Subscription 叫做 "Disposable" (可清理物件)。
Subscription
(訂閱)是使用observable.subscribe()
建立一個觀察者物件時.所返回的一個物件.它主要就是使用unsubscribe() 函式
主動關閉Observer
對Observable
的監聽訂閱.其使用方法如下:
var observable = Rx.Observable.interval(1000);
var subscription = observable.subscribe(x => console.log(x));
// 稍後:
// 這會取消正在進行中的 Observable 執行
// Observable 執行是通過使用觀察者呼叫 subscribe 方法啟動的
subscription.unsubscribe();複製程式碼
Operators (操作符)
操作符是 Observable 型別上的方法,比如 .map(...)、.filter(...)、.merge(...),等等。當操作符被呼叫時,它們不會改變已經存在的 Observable 例項。相反,它們返回一個新的 Observable ,它的 subscription 邏輯基於第一個 Observable 。
操作符是函式,它基於當前的 Observable 建立一個新的 Observable。這是一個無副作用的操作:前面的 Observable 保持不變。
就本質上而言Operators
就是一個純粹的函式.它可以接收一個 Observable 作為輸入.並在經過內部的一系列處理後返回一個新的Observable
作為輸出.流向下一個操作.
Subject (主體)
什麼是 Subject? - RxJS Subject 是一種特殊型別的 Observable,它允許將值多播給多個觀察者,所以 Subject 是多播的,而普通的 Observables 是單播的(每個已訂閱的觀察者都擁有 Observable 的獨立執行)。
Subject 像是 Observalbe,但是可以多播給多個觀察者。Subject 還像是 EventEmitters,維護著多個監聽器的登錄檔。
每一個Subject
都同時是一個Observable
和Observer
.對於Subject
你可以使用subscribe
方法並指定一個觀察者.也可以呼叫next(v)
、error(e)
和 complete()
來處理接受道到值.示例如下:
var subject = new Rx.Subject();
subject.subscribe({
next: (v) => console.log('observerA: ' + v)
});
subject.subscribe({
next: (v) => console.log('observerB: ' + v)
});
subject.next(1);
subject.next(2);複製程式碼
在上面的示例中,我們為 Subject 新增了兩個觀察者,然後給 Subject 提供一些值
Schedulers (排程器)
什麼是排程器? - 排程器控制著何時啟動 subscription 和何時傳送通知。它由三部分組成:
- 排程器是一種資料結構。 它知道如何根據優先順序或其他標準來儲存任務和將任務進行排序。
- 排程器是執行上下文。 它表示在何時何地執行任務(舉例來說,立即的,或另一種回撥函式機制(比如 setTimeout 或 process.nextTick),或動畫幀)。
- 排程器有一個(虛擬的)時鐘。 排程器功能通過它的 getter 方法 now() 提供了“時間”的概念。在具體排程器上安排的任務將嚴格遵循該時鐘所表示的時間。
排程器可以讓你規定 Observable 在什麼樣的執行上下文中傳送通知給它的觀察者。
上面是我最近學習RxJS時一些粗淺的總結,希望對大家有所幫助.如果文中有何不當之處請予以斧正,資訊.
參考資料
我的個人網址: www.wangyiming19950222.com