Operators
skip
我們昨天介紹了 take
可以取前幾個(gè)送出的元素俭正,今天介紹可以略過(guò)前幾個(gè)送出元素的 operator: skip
搜立,范例如下:
var source = Rx.Observable.interval(1000);
var example = source.skip(3);
example.subscribe({
next: (value) => { console.log(value); },
error: (err) => { console.log('Error: ' + err); },
complete: () => { console.log('complete'); }
});
// 3
// 4
// 5...
原本從 0 開(kāi)始的就會(huì)變成從 3 開(kāi)始蒋失,但是記得原本元素的等待時(shí)間仍然存在暂题,也就是說(shuō)此范例第一個(gè)取得的元素需要等 4 秒裹唆,用 Marble Diagram 表示如下。
source : ----0----1----2----3----4----5--....
skip(3)
example: -------------------3----4----5--...
takeLast
除了可以用 take 取前幾個(gè)之外婴氮,我們也可以倒過(guò)來(lái)取最后幾個(gè)斯棒,范例如下:
var source = Rx.Observable.interval(1000).take(6);
var example = source.takeLast(2);
example.subscribe({
next: (value) => { console.log(value); },
error: (err) => { console.log('Error: ' + err); },
complete: () => { console.log('complete'); }
});
// 4
// 5
// complete
這裡我們先取了前 6 個(gè)元素,再取最后兩個(gè)主经。所以最后會(huì)送出 4, 5, complete名船,這裡有一個(gè)重點(diǎn),就是 takeLast 必須等到整個(gè) observable 完成(complete)旨怠,才能知道最后的元素有哪些渠驼,并且同步送出,如果用 Marble Diagram 表示如下
source : ----0----1----2----3----4----5|
takeLast(2)
example: ------------------------------(45)|
這裡可以看到 takeLast 后鉴腻,比須等到原本的 observable 完成后迷扇,才立即同步送出 4, 5, complete。
last
跟 take(1)
相同爽哎,我們有一個(gè) takeLast(1)
的簡(jiǎn)化寫(xiě)法蜓席,那就是 last()
用來(lái)取得最后一個(gè)元素。
var source = Rx.Observable.interval(1000).take(6);
var example = source.last();
example.subscribe({
next: (value) => { console.log(value); },
error: (err) => { console.log('Error: ' + err); },
complete: () => { console.log('complete'); }
});
// 5
// complete
用 Marble Diagram 表示如下
source : ----0----1----2----3----4----5|
last()
example: ------------------------------(5)|
concat
concat
可以把多個(gè) observable 實(shí)例合併成一個(gè)课锌,范例如下
var source = Rx.Observable.interval(1000).take(3);
var source2 = Rx.Observable.of(3)
var source3 = Rx.Observable.of(4,5,6)
var example = source.concat(source2, source3);
example.subscribe({
next: (value) => { console.log(value); },
error: (err) => { console.log('Error: ' + err); },
complete: () => { console.log('complete'); }
});
// 0
// 1
// 2
// 3
// 4
// 5
// 6
// complete
跟 concatAll
一樣厨内,必須先等前一個(gè) observable 完成(complete)祈秕,才會(huì)繼續(xù)下一個(gè),用 Marble Diagram 表示如下雏胃。
source : ----0----1----2|
source2: (3)|
source3: (456)|
concat()
example: ----0----1----2(3456)|
另外 concat 還可以當(dāng)作靜態(tài)方法使用
var source = Rx.Observable.interval(1000).take(3);
var source2 = Rx.Observable.of(3);
var source3 = Rx.Observable.of(4,5,6);
var example = Rx.Observable.concat(source, source2, source3);
example.subscribe({
next: (value) => { console.log(value); },
error: (err) => { console.log('Error: ' + err); },
complete: () => { console.log('complete'); }
});
startWith
startWith
可以在 observable 的一開(kāi)始塞要發(fā)送的元素请毛,有點(diǎn)像 concat
但參數(shù)不是 observable 而是要發(fā)送的元素,使用范例如下
var source = Rx.Observable.interval(1000);
var example = source.startWith(0);
example.subscribe({
next: (value) => { console.log(value); },
error: (err) => { console.log('Error: ' + err); },
complete: () => { console.log('complete'); }
});
// 0
// 0
// 1
// 2
// 3...
這裡可以看到我們?cè)?source 的一開(kāi)始塞了一個(gè) 0
瞭亮,讓 example 會(huì)在一開(kāi)始就立即送出 0
方仿,用 Marble Diagram 表示如下
source : ----0----1----2----3--...
startWith(0)
example: (0)----0----1----2----3--...
記得 startWith 的值是一開(kāi)始就同步發(fā)出的,這個(gè) operator 很常被用來(lái)保存程式的起始狀態(tài)统翩!
merge
merge
跟 concat
一樣都是用來(lái)合併 observable仙蚜,但他們?cè)谛袨樯嫌蟹浅4蟮牟煌?/p>
讓我們直接來(lái)看例子吧
var source = Rx.Observable.interval(500).take(3);
var source2 = Rx.Observable.interval(300).take(6);
var example = source.merge(source2);
example.subscribe({
next: (value) => { console.log(value); },
error: (err) => { console.log('Error: ' + err); },
complete: () => { console.log('complete'); }
});
// 0
// 0
// 1
// 2
// 1
// 3
// 2
// 4
// 5
// complete
上面可以看得出來(lái),merge
把多個(gè) observable 同時(shí)處理厂汗,這跟 concat
一次處理一個(gè) observable 是完全不一樣的委粉,由于是同時(shí)處理行為會(huì)變得較為複雜,這裡我們用 Marble Diagram 會(huì)比較好解釋娶桦。
source : ----0----1----2|
source2: --0--1--2--3--4--5|
merge()
example: --0-01--21-3--(24)--5|
這裡可以看到 merge
之后的 example 在時(shí)間序上同時(shí)在跑 source 與 source2贾节,當(dāng)兩件事情同時(shí)發(fā)生時(shí),會(huì)同步送出資料(被 merge 的在后面)趟紊,當(dāng)兩個(gè) observable 都結(jié)束時(shí)才會(huì)真的結(jié)束。
merge 同樣可以當(dāng)作靜態(tài)方法用
var source = Rx.Observable.interval(500).take(3);
var source2 = Rx.Observable.interval(300).take(6);
var example = Rx.Observable.merge(source, source2);
example.subscribe({
next: (value) => { console.log(value); },
error: (err) => { console.log('Error: ' + err); },
complete: () => { console.log('complete'); }
});
merge 的邏輯有點(diǎn)像是 OR(||)碰酝,就是當(dāng)兩個(gè) observable 其中一個(gè)被觸發(fā)時(shí)都可以被處理霎匈,這很常用在一個(gè)以上的按鈕具有部分相同的行為。
例如一個(gè)影片播放器有兩個(gè)按鈕送爸,一個(gè)是暫停(II)铛嘱,另一個(gè)是結(jié)束播放(口)。這兩個(gè)按鈕都具有相同的行為就是影片會(huì)被停止袭厂,只是結(jié)束播放會(huì)讓影片回到 00 秒墨吓,這時(shí)我們就可以把這兩個(gè)按鈕的事件 merge 起來(lái)處理影片暫停這件事。
var stopVideo = Rx.Observable.merge(stopButton, endButton);
stopVideo.subscribe(() => {
// 暫停播放影片
})
今日小結(jié)
今天介紹的六個(gè) operators 都是平時(shí)很容易用到的纹磺,我們之后的范例也有機(jī)會(huì)再遇到帖烘。希望讀者們能自己試試這些方法,之后使用時(shí)會(huì)比較有印象橄杨!
不知道讀者今天有沒(méi)有收穫呢秘症? 如果有任何問(wèn)題,歡迎在下方留言給我式矫,謝謝乡摹。