RxJS——你知道 reduce 和 withLatestFrom 的細(xì)節(jié)嗎?

之前的文章中我們介紹過(guò)了 scan 操作符钧嘶,和 JavaScript 數(shù)組的 reduce 函數(shù)很像棠众。其實(shí)在 RxJS 中也有 reduce 操作符∮芯觯可是既然已經(jīng)有了 scan 闸拿,為什么還會(huì)有 reduce?當(dāng)然是有差別的书幕,reduce 操作符必須要等到上游事件流發(fā)生 complete 事件后才會(huì)輸出新荤。比如下面的程序是永遠(yuǎn)看不到輸出的:

combineLatest(
  timer$,
  input$,
  (timeValue, inputValue) => ({ count: timeValue, input: inputValue })
)
  .pipe(
  reduce((acc, curr) => acc + 1, 0),
  tap(console.log)
)

因?yàn)樯嫌问录鞑粫?huì)產(chǎn)生 complete 事件。再來(lái)看看下面的代碼:

combineLatest(
  timer$,
  input$,
  (timeValue, inputValue) => ({ count: timeValue, input: inputValue })
)
  .pipe(
  takeWhile(data => data.count < 3),
  reduce((acc, curr) => acc + 1, 0),
  tap(console.log)
)

這段程序會(huì)輸出嗎台汇?當(dāng)然苛骨,因?yàn)?taikeWhile 操作符的關(guān)系篱瞎,當(dāng)上游的事件對(duì)象的 count 屬性變成 3 時(shí),就會(huì)產(chǎn)生 complete 事件痒芝,reduce 操作就會(huì)把累積的數(shù)字輸出俐筋。因此當(dāng)我們需要知道累積函數(shù)每一步的值時(shí)就用 scan 操作符,如果只對(duì)最終結(jié)果感興趣就用 reduce 操作符严衬,但事件流一定是可以正常結(jié)束的才可以澄者。

下面我們來(lái)看看另一對(duì)有同樣行為又有微妙不同的操作符。combineLatest 和 withLatestFrom 操作符瞳步。讓我們精簡(jiǎn)下代碼闷哆,這樣更能看清它們的區(qū)別腰奋,首先看下 combineLatest 操作符:

const combineTimerAndInput$ = combineLatest(
  timer$,
  input$,
  (timeValue, inputValue) => ({ count: timeValue, input: inputValue })
)

const subscription = combineTimerAndInput$
.subscribe(
  x => console.log(x),
  err => console.log(err),
  () => console.log("complete")
);

之前的文章已經(jīng)提到单起,combineLatest 操作符一定要等到被 combine 的所有流都產(chǎn)生事件才會(huì)輸出,我們這里是兩個(gè)流劣坊。我們這樣操作看下效果:

  1. 點(diǎn)擊開(kāi)始按鈕嘀倒;
  2. 等幾秒,在文本框輸入內(nèi)容局冰;
  3. 等幾秒测蘑,點(diǎn)擊暫停按鈕;
  4. 在文本框輸入內(nèi)容康二;

動(dòng)圖如下:

總結(jié)一下現(xiàn)象:一開(kāi)始只有定時(shí)器產(chǎn)生事件碳胳,因此沒(méi)有輸出,當(dāng)在文本框開(kāi)始輸入內(nèi)容時(shí)沫勿,文本流產(chǎn)生了事件挨约。這樣兩個(gè)流都產(chǎn)生了事件,必然開(kāi)始有輸出产雹。但當(dāng)我們停止在文本框輸入時(shí)诫惭,文本流就沒(méi)有事件產(chǎn)生了,定時(shí)器還在不斷產(chǎn)生事件蔓挖,按理說(shuō)應(yīng)該停止輸出了夕土,但 combineLatest 依然輸出。同樣的瘟判,當(dāng)我們點(diǎn)擊了暫停按鈕怨绣,定時(shí)器流就沒(méi)有事件產(chǎn)生了,文本流這是也沒(méi)有事件產(chǎn)生拷获,因此是沒(méi)有輸出的梨熙,但當(dāng)我們保持暫停,在文本框輸入內(nèi)容時(shí)刀诬,combineLatest 又會(huì)開(kāi)始輸出咽扇。這就是 combineLatest 的工作機(jī)制邪财。只要被組合的流中都有過(guò)值,那么只要被組合的流中有一個(gè)產(chǎn)生新事件质欲,其他流都以最后一次產(chǎn)生的事件作為新事件共同輸出树埠。接下來(lái)看看 withLatestFrom 操作符,大家都會(huì)對(duì)這段解釋有更清晰的認(rèn)識(shí)嘶伟。

代碼如下:

const subscription = timer$
.pipe(
  withLatestFrom(input$, (timeValue, inputValue) => ({
    count: timeValue,
    input: inputValue
  })),
)
.subscribe(
  x => console.log(x),
  err => console.log(err),
  () => console.log("complete")
);

首先怎憋,withLatestFrom 操作符是個(gè)對(duì)象方法,不像 combineLatest 是個(gè)靜態(tài)方法(combineLatest 在之前 RxJS 版本中也是對(duì)象方法)九昧。其次我們看到 withLatestFrom 的用法和 combineLatest 是一致的绊袋。測(cè)試步驟如下:

  1. 點(diǎn)擊開(kāi)始按鈕;
  2. 等幾秒铸鹰,在文本框輸入內(nèi)容癌别;
  3. 等幾秒,點(diǎn)擊暫停按鈕蹋笼;
  4. 在文本框輸入內(nèi)容展姐;
  5. 再次點(diǎn)擊開(kāi)始按鈕;

動(dòng)圖如下:

前面三步的效果和 combineLatest 是一樣的剖毯,到了第四步在文本框輸入內(nèi)容時(shí)圾笨,沒(méi)有了輸出;第五步又開(kāi)始有了輸出逊谋±薮铮總結(jié)一下:其實(shí)從 withLatestFrom 是對(duì)象函數(shù)就能看出,它是需要有事件流作為基礎(chǔ)的胶滋,combineLatest 則不然板鬓,是用來(lái)創(chuàng)造事件流的。也就是說(shuō)镀钓,當(dāng)上游事件流中沒(méi)有事件產(chǎn)生時(shí)穗熬,withLatestFrom 是不會(huì)有輸出的。符如其名丁溅,withLatestFrom 會(huì)把上游事件流中的事件和接收參數(shù)中的事件流的最后一個(gè)值一起進(jìn)行處理后輸出唤蔗。

如有任何問(wèn)題,請(qǐng)關(guān)注微信公眾號(hào)“讀一讀我”窟赏。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末妓柜,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子涯穷,更是在濱河造成了極大的恐慌棍掐,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,542評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拷况,死亡現(xiàn)場(chǎng)離奇詭異作煌,居然都是意外死亡掘殴,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)粟誓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)奏寨,“玉大人,你說(shuō)我怎么就攤上這事鹰服〔⊥” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,021評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵悲酷,是天一觀的道長(zhǎng)套菜。 經(jīng)常有香客問(wèn)我,道長(zhǎng)设易,這世上最難降的妖魔是什么逗柴? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,682評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮亡嫌,結(jié)果婚禮上嚎于,老公的妹妹穿的比我還像新娘掘而。我一直安慰自己挟冠,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,792評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布袍睡。 她就那樣靜靜地躺著知染,像睡著了一般。 火紅的嫁衣襯著肌膚如雪斑胜。 梳的紋絲不亂的頭發(fā)上控淡,一...
    開(kāi)封第一講書(shū)人閱讀 49,985評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音止潘,去河邊找鬼掺炭。 笑死,一個(gè)胖子當(dāng)著我的面吹牛凭戴,可吹牛的內(nèi)容都是我干的涧狮。 我是一名探鬼主播,決...
    沈念sama閱讀 39,107評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼么夫,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼者冤!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起档痪,我...
    開(kāi)封第一講書(shū)人閱讀 37,845評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤涉枫,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后腐螟,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體愿汰,經(jīng)...
    沈念sama閱讀 44,299評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡困后,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,612評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了衬廷。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片操灿。...
    茶點(diǎn)故事閱讀 38,747評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖泵督,靈堂內(nèi)的尸體忽然破棺而出趾盐,到底是詐尸還是另有隱情,我是刑警寧澤小腊,帶...
    沈念sama閱讀 34,441評(píng)論 4 333
  • 正文 年R本政府宣布救鲤,位于F島的核電站,受9級(jí)特大地震影響秩冈,放射性物質(zhì)發(fā)生泄漏本缠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,072評(píng)論 3 317
  • 文/蒙蒙 一入问、第九天 我趴在偏房一處隱蔽的房頂上張望丹锹。 院中可真熱鬧,春花似錦芬失、人聲如沸楣黍。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,828評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)租漂。三九已至,卻和暖如春颊糜,著一層夾襖步出監(jiān)牢的瞬間哩治,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,069評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工衬鱼, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留业筏,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,545評(píng)論 2 362
  • 正文 我出身青樓鸟赫,卻偏偏與公主長(zhǎng)得像蒜胖,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子惯疙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,658評(píng)論 2 350