30 天精通 RxJS (09): Observable Operator - skip, takeLast, last, concat, startWith, merge

轉(zhuǎn)載

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...

JSBin | JSFiddle

原本從 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

JSBin | JSFiddle

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'); }
});

JSBin | JSFiddle

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

mergeconcat 一樣都是用來(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

JSBin | JSFiddle

上面可以看得出來(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)題,歡迎在下方留言給我式矫,謝謝乡摹。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市采转,隨后出現(xiàn)的幾起案子聪廉,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件板熊,死亡現(xiàn)場(chǎng)離奇詭異框全,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)邻邮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)竣况,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人筒严,你說(shuō)我怎么就攤上這事丹泉。” “怎么了鸭蛙?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,369評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵摹恨,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我娶视,道長(zhǎng)晒哄,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,799評(píng)論 1 285
  • 正文 為了忘掉前任肪获,我火速辦了婚禮寝凌,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘孝赫。我一直安慰自己较木,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,910評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布青柄。 她就那樣靜靜地躺著伐债,像睡著了一般。 火紅的嫁衣襯著肌膚如雪致开。 梳的紋絲不亂的頭發(fā)上峰锁,一...
    開(kāi)封第一講書(shū)人閱讀 50,096評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音双戳,去河邊找鬼虹蒋。 笑死,一個(gè)胖子當(dāng)著我的面吹牛飒货,可吹牛的內(nèi)容都是我干的千诬。 我是一名探鬼主播,決...
    沈念sama閱讀 39,159評(píng)論 3 411
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼膏斤,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼徐绑!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起莫辨,我...
    開(kāi)封第一講書(shū)人閱讀 37,917評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤傲茄,失蹤者是張志新(化名)和其女友劉穎毅访,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體盘榨,經(jīng)...
    沈念sama閱讀 44,360評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡喻粹,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,673評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了草巡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片守呜。...
    茶點(diǎn)故事閱讀 38,814評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖山憨,靈堂內(nèi)的尸體忽然破棺而出查乒,到底是詐尸還是另有隱情,我是刑警寧澤郁竟,帶...
    沈念sama閱讀 34,509評(píng)論 4 334
  • 正文 年R本政府宣布玛迄,位于F島的核電站,受9級(jí)特大地震影響棚亩,放射性物質(zhì)發(fā)生泄漏蓖议。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,156評(píng)論 3 317
  • 文/蒙蒙 一讥蟆、第九天 我趴在偏房一處隱蔽的房頂上張望勒虾。 院中可真熱鬧,春花似錦瘸彤、人聲如沸修然。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)低零。三九已至婆翔,卻和暖如春拯杠,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背啃奴。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,123評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工潭陪, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人最蕾。 一個(gè)月前我還...
    沈念sama閱讀 46,641評(píng)論 2 362
  • 正文 我出身青樓依溯,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親瘟则。 傳聞我的和親對(duì)象是個(gè)殘疾皇子黎炉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,728評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容