可觀察對象和觀察者模式的差別:
- 可觀察者對象不啟動(dòng)流媒體項(xiàng)目(streaming items),直到至少有一個(gè)觀察者訂閱(Observer)它(這句話很重要)
- 和迭代器類似鸵钝,一個(gè)可觀察者對象當(dāng)序列(sequence)完成時(shí)能發(fā)送信號(signal)
- 使用可觀察者,我們能夠聲明如何響應(yīng)它發(fā)出的序列元素庐镐,而不是響應(yīng)當(dāng)單獨(dú)的個(gè)體元素
- 我們可以高效的復(fù)制恩商,轉(zhuǎn)換和查詢序列,這些操作對所有序列元素都有效
Observables && Observer
有很多種方式創(chuàng)建Observables對象必逆,使用 create
方法(在Rxjs中稱之為操作符)是最明顯的方式怠堪。
Rx.Observable
接收一個(gè)以Observer
作為參數(shù)的回調(diào),這個(gè)回調(diào)函數(shù)定義可觀察對象如何發(fā)出值(emit values).
var observable = Rx.Observable.create(function(observer) {
observer.onNext('James');
observer.onNext('Jordan');
observer.onNext('Durant');
observer.onCompleted(); // 完成
})
當(dāng)訂閱這個(gè)可觀察對象名眉,它將調(diào)用 onNext
方法粟矿, 生成3個(gè)字符串,然后調(diào)用 onCompleted
發(fā)出信號璧针,表示序列完成嚷炉。我們使用 Observers 來訂閱 Observable
Observers
Observers訂閱可觀察對象,當(dāng)可觀察對象發(fā)生變化探橱,觀察者調(diào)用相關(guān)的方法申屹,它有3個(gè)方法:
-
onNext
: 相當(dāng)于觀察者模式中的 ``Update 方法 -
onError
: 可觀察對象發(fā)生錯(cuò)誤時(shí)調(diào)用绘证,它調(diào)用之后,再調(diào)用onNext
是無效的 -
onCompleted
: 發(fā)出信號哗讥,沒有更多數(shù)據(jù)了
創(chuàng)建觀察者:
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
接收函數(shù) onNext
嚷那,onError
,onCompleted
杆煞, 返回一個(gè)Observer實(shí)例魏宽,這些方法是可選的。比如有些無限序列(比如用戶一直點(diǎn)擊鼠標(biāo))决乎,onCompleted
是永遠(yuǎn)不會(huì)被調(diào)用的队询,如果有信心不發(fā)生錯(cuò)誤,onError
也是可以不用寫的构诚。
Observable ajax請求
使用可觀察對象來封裝一個(gè)ajax請求,返回一個(gè)可觀察對象實(shí)例:
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('未知錯(cuò)誤'));
};
xhr.send();
})
}
光有可觀察對象蚌斩,沒有觀察者,流是不會(huì)觸發(fā)的范嘱,下面是觀察者:
var test = getUrl('https://randomuser.me/api/')
// 訂閱一個(gè)觀察者
test.subscribe(
function onNext(x) {console.log('Result: ' + x)},
function onError(err) {console.log('Error: ' + err)},
function onCompleted() {console.log('done')}
);
此處我們可以發(fā)現(xiàn)送膳,我們沒有通過Rx.Observer.create
顯式的創(chuàng)建一個(gè)Observer, 而是通過 subscribe
操作符來創(chuàng)建Observer
操作符
在Rxjs中,轉(zhuǎn)換或查詢序列方法被稱之為 operators
(操作符)丑蛤。上面的ajax封裝可以使用已經(jīng)存在的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編程中,可以把所有的數(shù)據(jù)都當(dāng)作可觀察者對象受裹,不僅是異步數(shù)據(jù)碌补,比如數(shù)組等
常見的操作符
1.將數(shù)組變?yōu)榭捎^察者對象: 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('完成');}
)
//結(jié)果
Next: a
Next: b
Next: c
完成
2.將事件變?yōu)榭捎^察者對象: fromEvent(dom, eventType)
var allMoves = Rx.Observable
.fromEvent(document, 'mousemove')
// 訂閱
allMoves.subscribe(
function(e) {console.log(e.clientX, e.clientY);}
)
// 另外還可以對可觀察者對象進(jìn)行轉(zhuǎn)換過濾等
// 在allMoves基礎(chǔ)上
var movesOnTheLeft = allMoves.filter(function(e)
{return e.clientX < window.innerWidth/2}
)
movesOnTheLeft.subscribe(function(e) {console.log('鼠標(biāo)在左邊',e.clientX)})
3.將回調(diào)函數(shù)變?yōu)榭捎^察者對象: fromCallback()
| fromNodeCallback()
比如Nodejs中
var Rx = require('rx');
var fs = require('fs');
// 從readdir方法中創(chuàng)建可觀察者對象
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('完成');}
)
總結(jié)
初步認(rèn)識(shí)Rxjs,了解什么是可觀察對象,觀察者名斟,如何使用操作符來創(chuàng)建它們脑慧,本文主要使用 RxJS4.10版本,注意和5.0的區(qū)別。
使用到了 rxjs-dom
庫來完成ajax請求砰盐,初步了解的一些操作符:
create
subscribe
from
fromEvent
fromNodeCallback
可觀察者的2個(gè)方法(接受以observer為參數(shù)的回調(diào)函數(shù)):
observer.onNext()
observer.onCompleted()
觀察者的3個(gè)函數(shù):
function onNext() {}
function onError() {}
function onCompleted() {}