
rxjs(Reactive Extensions for JavaScript)是Javascript的響應(yīng)式擴(kuò)展, 響應(yīng)式的思路是把隨時間不斷變化的數(shù)據(jù)、狀態(tài)、事件等轉(zhuǎn)成可被觀察的序列(Observable Sequence),然后訂閱序列中對象的變化,一旦變化,就會執(zhí)行事先安排好的各種轉(zhuǎn)換和操作。
原文鏈接
rxjs適用于異步場景,可以用于優(yōu)化前端交互中的請求、事件。
rxjs特點(diǎn)
- 統(tǒng)一異步編程的規(guī)范,不管是Promise、ajax還是事件,通通封裝成序列(Observable Sequence),一旦有異步環(huán)節(jié)發(fā)生變更,觀察序列即可截獲發(fā)生變更的信息。
- 前端業(yè)務(wù)層和展現(xiàn)層解耦,比如展現(xiàn)層不需要關(guān)心指定事件觸發(fā)時和DOM無關(guān)的處理邏輯。同時業(yè)務(wù)層也能組裝異步操作中多個異步邏輯之間的關(guān)系,無需暴露給展現(xiàn)層。展現(xiàn)層關(guān)心的是:異步操作其中環(huán)節(jié)的數(shù)據(jù)變化。
- rxjs開發(fā)業(yè)務(wù)層具有高彈性,高穩(wěn)定性,高實(shí)時性等特點(diǎn)。
rxjs實(shí)例概念
- Observable: 可觀察的數(shù)據(jù)序列.
- Observer: 觀察者實(shí)例,決定何時觀察指定數(shù)據(jù).
- Subscription: 觀察數(shù)據(jù)序列返回訂閱實(shí)例.
- Operators: Observable的操作方法,包括轉(zhuǎn)換數(shù)據(jù)序列,過濾等,所有的Operators方法接受的參數(shù)是上一次發(fā)送的數(shù)據(jù)變更的值,而方法返回值稱為發(fā)射新數(shù)據(jù)變更.
- Subject: 被觀察對象.
- Schedulers: 控制調(diào)度并發(fā),即當(dāng)Observable接受Subject的變更響應(yīng)時,可以通過scheduler設(shè)置響應(yīng)方式,目前內(nèi)置的響應(yīng)可以調(diào)用Object.keys(Rx.Subject)查看。
- Observable四個生命周期:創(chuàng)建 、訂閱 、 執(zhí)行 、銷毀。
- 創(chuàng)建Obervable,返回被觀察的序列源實(shí)例,該實(shí)例不具備發(fā)送數(shù)據(jù)的能力,相比之下通過new Rx.Subject創(chuàng)建的觀察對象實(shí)例具備發(fā)送數(shù)據(jù)源的能力。
- 通過序列源實(shí)例可以訂閱序列發(fā)射新數(shù)據(jù)變更時的響應(yīng)方法(回調(diào)方法)。
- 響應(yīng)的動作實(shí)際上就是Observable的執(zhí)行。
- 通過序列源實(shí)例可以銷毀,而當(dāng)訂閱方法發(fā)生錯誤時也會自動銷毀。
- 序列源實(shí)例的catch方法可以捕獲訂閱方法發(fā)生的錯誤,同時序列源實(shí)例可以接受從catch方法返回值,作為新的序列源實(shí)例。
rxjs操作符
rxjs中提供了很多操作符,用于創(chuàng)建Observable對象
import Rx from 'rxjs';
create
let observable = Rx.Observable
.create((observer)=> {
observer.next('hello');
observer.next('world');
});
//訂閱Observable
observable.subscribe((value)=> {
console.log(value);
});
輸出:hello
world
of
轉(zhuǎn)換值變量
let observable = Rx.Observable.of('hello', 'world');
observable.subscribe({
next: (value)=> {
console.log(value);
},
complete: ()=> {
console.log('complete');
},
error: (error)=> {
console.log(error);
}
});
輸出:hello
world
complete
from
轉(zhuǎn)換數(shù)組變量
let array = [1, 2, 3];
let observable = Rx.Observable.from(array);
observable.subscribe({
next: (value)=> {
console.log(value);
},
complete: ()=> {
console.log('complete');
},
error: (error)=> {
console.log(error);
}
});
輸出:1
2
3
complete
fromEvent
轉(zhuǎn)換事件變量
Rx.Observable.fromEvent(document.querySelector('button'), 'click');
fromPromise
轉(zhuǎn)換Promise(承諾)變量
let observable = Rx.Observable
.fromPromise(new Promise((resolve, reject) => {
setTimeout(() => {
resolve('hello world');
},3000)
}));
observable.subscribe({
next: (value)=> {
console.log(value);
},
complete: ()=> {
console.log('complete');
},
error: (error)=> {
console.log(error);
}
});
輸出:hello world
complete
empty
empty操作符返回一個空的Observable,訂閱該對象,它會立即返回complete信息。
never
never操作符會返回一個無窮的Observable,訂閱該對象,什么事情都不會發(fā)生,它是一個一直存在卻什么都不做的Observable對象。
interval
interval操作符支持一個數(shù)值類型的參數(shù),用于表示定時的間隔。
let observable = Rx.Observable.interval(1000);
observable.subscribe({
next: (value)=> {
console.log(value);
},
complete: ()=> {
console.log('complete');
},
error: (error)=> {
console.log(error);
}
});
輸出:0
1
2
...
上面代碼表示每隔1s,會輸出一個遞增的值,初始值從0開始。
timer
timer操作符支持兩個參數(shù),第一個參數(shù)用于設(shè)定發(fā)送第一個值需等待的時間,第二個參數(shù)表示第一次發(fā)送后,發(fā)送其它值的間隔時間。
let observable = Rx.Observable.timer(1000, 5000);
observable.subscribe({
next: (value)=> {
console.log(value);
},
complete: ()=> {
console.log('complete');
},
error: (error)=> {
console.log(error);
}
});
輸出:0 //1s后
1 //5s后
2 //5s后
...
Pull vs Push
Pull和Push是數(shù)據(jù)生產(chǎn)者和數(shù)據(jù)消費(fèi)者兩種不同的交流方式
Pull
在Pull體系中,數(shù)據(jù)的消費(fèi)者決定何時從數(shù)據(jù)生產(chǎn)者那里獲取數(shù)據(jù),而生產(chǎn)者自身并不會意識到什么時候數(shù)據(jù)將會被發(fā)送給消費(fèi)者。
每個JavaScript函數(shù)都是一個Pull體系,函數(shù)是數(shù)據(jù)的生產(chǎn)者,調(diào)用函數(shù)的代碼通過拉出一個單一的返回值來消費(fèi)該數(shù)據(jù)。
ES6中的iterator迭代器和generator生成器是另一種Pull體系,調(diào)用iterator.next()的代碼是消費(fèi)者,可從中拉取多個值。
Push
在Push體系中,數(shù)據(jù)的生產(chǎn)者決定何時發(fā)送數(shù)據(jù)給消費(fèi)者,消費(fèi)者不會在接收數(shù)據(jù)之前意識到它將要接收這個數(shù)據(jù)。
Promise是最常見的Push體系,一個Promise(數(shù)據(jù)的生產(chǎn)者)發(fā)送一個resolved(成功狀態(tài))或reject(失敗狀態(tài))來執(zhí)行一個回調(diào)(數(shù)據(jù)消費(fèi)者),但是不同于函數(shù)的地方的是:Promise決定著何時數(shù)據(jù)才被推送至這個回調(diào)函數(shù)。
RxJS引入了Observables(可觀察對象),一個全新的Push體系。一個可觀察對象是一個產(chǎn)生多值的生產(chǎn)者,當(dāng)產(chǎn)生新數(shù)據(jù)的時候,會主動推送給Observer(觀察者)。
| 生產(chǎn)者 | 消費(fèi)者 | |
|---|---|---|
| Pull | 被請求的時候產(chǎn)生數(shù)據(jù) | 決定何時請求數(shù)據(jù) |
| Push | 按自己的節(jié)奏生產(chǎn)數(shù)據(jù) | 對接收的數(shù)據(jù)進(jìn)行處理 |
Observable vs Promise
| 單值 | 多值 | |
|---|---|---|
| Pull | 函數(shù) | 遍歷器 |
| Push | Promise | Observable |
Promise
- 返回單個值
- 不可取消
Observable
- 隨著時間的推移發(fā)出多個值
- 可以取消
- 支持 map、filter、reduce 等操作符
- 延遲執(zhí)行,當(dāng)訂閱的時候才會開始執(zhí)行