Observable 的 Operators 是實例應用上最重要的部份,咱們須要瞭解各類 Operators 的使用方式,才能輕鬆實現各類需求!javascript
這是【30天精通 RxJS】的 07 篇,若是還沒看過 06 篇能夠往這邊走:
30 天精通 RxJS (06): 創建 Observable(二)%EF%BC%9A%20%E5%BB%BA%E7%AB%8B%20Observable(%E4%BA%8C).md)java
昨天咱們把全部創建 Observable 實例的 operators 講完了,接下來咱們要講關於轉換(Transformation)、過濾(Filter)、合併(Combination)等操做方法。先來讓咱們看看什麼是 Operatorgit
Operators 就是一個個被附加到 Observable 型別的函數,例如像是 map, filter, contactAll... 等等,全部這些函數都會拿到本來的 observable 並回傳一個新的 observable,就像有點像下面這個樣子github
var people = Rx.Observable.of('Jerry', 'Anna');
function map(source, callback) {
return Rx.Observable.create((observer) => {
return source.subscribe(
(value) => {
try{
observer.next(callback(value));
} catch(e) {
observer.error(e);
}
},
(err) => { observer.error(err); },
() => { observer.complete() }
)
})
}
var helloPeople = map(people, (item) => item + ' Hello~');
helloPeople.subscribe(console.log);
// Jerry Hello~
// Anna Hello~複製代碼
這裏能夠看到咱們寫了一個 map 的函數,它接收了兩個參數,第一個是本來的 observable,第二個是 map 的 callback function。map 內部第一件事就是用 create
創建一個新的 observable 並回傳,而且在內部訂閱本來的 observable。函數
固然咱們也能夠直接把 map 塞到 Observable.prototype
學習
function map(callback) {
return Rx.Observable.create((observer) => {
return this.subscribe(
(value) => {
try{
observer.next(callback(value));
} catch(e) {
observer.error(e);
}
},
(err) => { observer.error(err); },
() => { observer.complete() }
)
})
}
Rx.Observable.prototype.map = map;
var people = Rx.Observable.of('Jerry', 'Anna');
var helloPeople = people.map((item) => item + ' Hello~');
helloPeople.subscribe(console.log);
// Jerry Hello~
// Anna Hello~複製代碼
這裏有兩個重點是咱們必定要知道的,每一個 operator 都會回傳一個新的 observable,而咱們能夠透過 create
的方法創建各類 operator。ui
在 RxJS 5 的實例中,其實每一個 operator 是透過原來 observable 的 lift 方法來創建新的 observable,這個方法會在新回傳的 observable 事件內偷塞兩個屬性,分別是 source(來源) 與 operator,記錄本來的資料源跟當前使用的 operator。this
其實 lift 方法仍是用 new Observable(跟 create 同樣)。至於爲何要獨立出這個方法,除了更好的封裝之外,主要的緣由是爲了讓 RxJS 5 的使用者能更好的 debug。關於 RxJS 5 的除錯方式,咱們會專門寫一篇來說解!spa
這裏咱們只是簡單的實例 operator。若是以後實例上,想要不影響本來的 Observable 又可以自訂 operator 能夠參考官方的這份文件。(如今先不用看)
其實 RxJS 提供的各類 operators 已經很是夠用了,不太須要咱們本身創造 operator,這裏只是想讓你們先對 operator 的創建有個基本的觀念,以後在學習的過程當中會比較輕鬆。
在咱們開始介紹 RxJS 的 operators 前,爲了能讓咱們更好地理解各類 operators,咱們須要先訂定一個簡單的方式來表達 observable!
咱們在傳達事物時,文字實際上是最糟的手段,雖然文字是咱們平時溝通的基礎,但經常千言萬語也比不過一張清楚的圖。若是咱們能訂定 observable 的圖示,就能讓咱們更方便的溝通及理解 observable 的各類 operators!
咱們把描繪 observable 的圖示稱爲 Marble diagrams,在網路上 RxJS 有很是多的 Marble diagrams,規則大體上都是相同的,這裏爲了方便撰寫以及跟讀者的留言互動,因此採用相似 ASCII 的繪畫方式。
咱們用 -
來表達一小段時間,這些 -
串起就表明一個 observable。
----------------複製代碼
X
(大寫 X)則表明有錯誤發生
---------------X複製代碼
|
則表明 observable 結束
----------------|複製代碼
在這個時間序當中,咱們可能會發發送值(value),若是值是數字則直接用阿拉伯數字取代,其餘的資料型別則用相近的英文符號表明,這裏咱們用 interval
舉例
var source = Rx.Observable.interval(1000);複製代碼
source
的圖形就會長像這樣
-----0-----1-----2-----3--...複製代碼
當 observable 是同步送值的時候,例如
var source = Rx.Observable.of(1,2,3,4);複製代碼
source
的圖形就會長像這樣
(1234)|複製代碼
小括號表明着同步發生。
另外的 Marble diagrams 也可以表達 operator 的先後轉換,例如
var source = Rx.Observable.interval(1000);
var newest = source.map(x => x + 1);複製代碼
這時 Marble diagrams 就會長像這樣
source: -----0-----1-----2-----3--...
map(x => x + 1)
newest: -----1-----2-----3-----4--...複製代碼
最上面是本來的 observable,中間是 operator,下面則是新的 observable。
以上就是 Marble diagrams 如何表示 operator 對 observable 的操做,這能讓咱們更好的理解各個 operator。
Marble Diagrams 相關資源:rxmarbles.com/
最後讓咱們來看幾個簡單的 Operators!
Observable 的 map 方法使用上跟數組的 map 是同樣的,咱們傳入一個 callback function,這個 callback function 會帶入每次發發送來的元素,而後咱們回傳新的元素,以下
var source = Rx.Observable.interval(1000);
var newest = source.map(x => x + 1);
newest.subscribe(console.log);
// 1
// 2
// 3
// 4
// 5..複製代碼
用 Marble diagrams 表達就是
source: -----0-----1-----2-----3--...
map(x => x + 1)
newest: -----1-----2-----3-----4--...複製代碼
咱們有另一個方法跟 map 很像,叫 mapTo
mapTo 能夠把傳進來的值改爲一個固定的值,以下
var source = Rx.Observable.interval(1000);
var newest = source.mapTo(2);
newest.subscribe(console.log);
// 2
// 2
// 2
// 2..複製代碼
mapTo 用 Marble diagrams 表達
source: -----0-----1-----2-----3--...
mapTo(2)
newest: -----2-----2-----2-----2--...複製代碼
filter 在使用上也跟數組的相同,咱們要傳入一個 callback function,這個 function 會傳入每一個被髮送的元素,而且回傳一個 boolean 值,若是爲 true 的話就會保留,若是爲 false 就會被濾掉,以下
var source = Rx.Observable.interval(1000);
var newest = source.filter(x => x % 2 === 0);
newest.subscribe(console.log);
// 0
// 2
// 4
// 6..複製代碼
filter 用 Marble diagrams 表達
source: -----0-----1-----2-----3-----4-...
filter(x => x % 2 === 0)
newest: -----0-----------2-----------4-...複製代碼
讀者應該有發現 map, filter 這些方法其實都跟數組的相同,由於這些都是 functional programming 的通用函數,就算換個語言也有機會看到相同的命名及相同的用法。
實際上 Observable 跟 Array 的 operators(map, filter),在行爲上仍是有極大的差別。當咱們的資料量很大時,Observable 的效能會好上很是多。咱們會有一天專門講這個部份!
今天咱們講了 Observable Operators 的相關知識,有如下幾個重點
不知道今天讀者有沒有收穫呢?歡迎在下方留言給我,這是精通 RxJS 的第 07 篇!