可觀察對象和觀察者模式的差別:
- 可觀察者對象不啟動流媒體項目(streaming items),直到至少有一個觀察者訂閱(Observer)它(這句話很重要)
- 和迭代器類似,一個可觀察者對象當序列(sequence)完成時能發送信號(signal)
- 使用可觀察者,我們能夠聲明如何響應它發出的序列元素,而不是響應當單獨的個體元素
- 我們可以高效的復制,轉換和查詢序列,這些操作對所有序列元素都有效
Observables && Observer
有很多種方式創建Observables對象,使用 create
方法(在Rxjs中稱之為操作符)是最明顯的方式。
Rx.Observable
接收一個以Observer
作為參數的回調,這個回調函數定義可觀察對象如何發出值(emit values).
var observable = Rx.Observable.create(function(observer) {
observer.onNext('James');
observer.onNext('Jordan');
observer.onNext('Durant');
observer.onCompleted(); // 完成
})
當訂閱這個可觀察對象,它將調用 onNext
方法, 生成3個字符串,然后調用 onCompleted
發出信號,表示序列完成。我們使用 Observers 來訂閱 Observable
Observers
Observers訂閱可觀察對象,當可觀察對象發生變化,觀察者調用相關的方法,它有3個方法:
-
onNext
: 相當于觀察者模式中的 ``Update 方法 -
onError
: 可觀察對象發生錯誤時調用,它調用之后,再調用onNext
是無效的 -
onCompleted
: 發出信號,沒有更多數據了
創建觀察者:
var observer = Rx.Observer.create(
function onNext(x) { console.log('next: ' + x);},
function onError(err) { console.log('Error: ' + err); },
function onCompleted() { console.log('Done'); }
);
Rx.Observer.create
接收函數 onNext
,onError
,onCompleted
, 返回一個Observer實例,這些方法是可選的。比如有些無限序列(比如用戶一直點擊鼠標),onCompleted
是永遠不會被調用的,如果有信心不發生錯誤,onError
也是可以不用寫的。
Observable ajax請求
使用可觀察對象來封裝一個ajax請求,返回一個可觀察對象實例:
function getUrl(url) {
return Rx.Observable.create(function(observer) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onload = function() {
if (req.status === 200) {
observer.onNext(xhr.response);
observer.onCompleted();
} else {
observer.onError(new Error(xhr.statusText));
}
};
xhr.onerror = function() {
observer.onError(new Error('未知錯誤'));
};
xhr.send();
})
}
光有可觀察對象,沒有觀察者,流是不會觸發的,下面是觀察者:
var test = getUrl('https://randomuser.me/api/')
// 訂閱一個觀察者
test.subscribe(
function onNext(x) {console.log('Result: ' + x)},
function onError(err) {console.log('Error: ' + err)},
function onCompleted() {console.log('done')}
);
此處我們可以發現,我們沒有通過Rx.Observer.create
顯式的創建一個Observer, 而是通過 subscribe
操作符來創建Observer
操作符
在Rxjs中,轉換或查詢序列方法被稱之為 operators
(操作符)。上面的ajax封裝可以使用已經存在的rxjs-dom
庫來完成。
// 首先先引入rxjs-dom.js庫
// https://cdnjs.cloudflare.com/ajax/libs/rxjs-dom/7.0.3/rx.dom.compat.min.js
Rx.DOM.get('https://randomuser.me/api/')
.subscribe(
function onNext(data) {console.log(data.response)},
function onError(err) {console.log('Error: ' + err)},
)
在Rxjs編程中,可以把所有的數據都當作可觀察者對象,不僅是異步數據,比如數組等
常見的操作符
1.將數組變為可觀察者對象: from(arr)
Rx.Observable
.from(['a', 'b', 'c'])
.subscribe(
function(x) {console.log('Next: ' + x);}, // 可以不用寫方法名'onNext'
function(err) {console.log('Error: ' + err);},
function() {console.log('完成');}
)
//結果
Next: a
Next: b
Next: c
完成
2.將事件變為可觀察者對象: fromEvent(dom, eventType)
var allMoves = Rx.Observable
.fromEvent(document, 'mousemove')
// 訂閱
allMoves.subscribe(
function(e) {console.log(e.clientX, e.clientY);}
)
// 另外還可以對可觀察者對象進行轉換過濾等
// 在allMoves基礎上
var movesOnTheLeft = allMoves.filter(function(e)
{return e.clientX < window.innerWidth/2}
)
movesOnTheLeft.subscribe(function(e) {console.log('鼠標在左邊',e.clientX)})
3.將回調函數變為可觀察者對象: fromCallback()
| fromNodeCallback()
比如Nodejs中
var Rx = require('rx');
var fs = require('fs');
// 從readdir方法中創建可觀察者對象
var readdir = Rx.Observable.fromNodeCallback(fs.readdir);
var source = readdir('/users/someone');
var subscription = source.subscribe(
function(res) {console.log('目錄: ' + res);}, // 可以不用寫方法名'onNext'
function(err) {console.log('Error: ' + err);},
function() {console.log('完成');}
)
總結
初步認識Rxjs,了解什么是可觀察對象,觀察者,如何使用操作符來創建它們,本文主要使用 RxJS4.10版本,注意和5.0的區別。
使用到了 rxjs-dom
庫來完成ajax請求,初步了解的一些操作符:
create
subscribe
from
fromEvent
fromNodeCallback
可觀察者的2個方法(接受以observer為參數的回調函數):
observer.onNext()
observer.onCompleted()
觀察者的3個函數:
function onNext() {}
function onError() {}
function onCompleted() {}