我們知道 takeWhile 操作符在條件函數(shù)不滿足時(shí)立即觸發(fā)流的 complete 事件急侥,所表現(xiàn)出來的效果就是點(diǎn)擊任何按鈕都不再有任何反應(yīng)侮邀。
const addOneOrReset = (time = 1000) =>
merge(
interval(time).pipe(
takeUntil(pauseBtnClick$),
mapTo(addOne)
),
resetBtnClick$.pipe(mapTo(reset))
);
const time$ = merge(
startBtnClick$.pipe(mapTo(1000)),
halfBtnClick$.pipe(mapTo(500)),
quarterBtnClick$.pipe(mapTo(250))
);
const timer$ = time$.pipe(
switchMap(addOneOrReset),
startWith({ count: 0 }),
scan((acc, current) => current(acc)),
map(obj => obj.count),
tap(v => setTxt(v))
);
const subscription = timer$
.pipe(
takeWhile(data => data < 5),
)
.subscribe(
x => console.log(x),
err => console.log(err),
() => console.log("complete")
);
當(dāng)我們點(diǎn)擊開始按鈕時(shí)贝润,定時(shí)器流開始產(chǎn)生事件。由于 takeWhile 操作符的原因打掘,到 5 時(shí)控制臺(tái)將輸出 complete。
這里先說明下界面和控制臺(tái)輸出的數(shù)字為什么不一樣亡笑。因?yàn)榻缑娓率窃?tap 操作符做的,要先于 takeWhile 操作符况芒。當(dāng)界面更新為 5 時(shí)叶撒,takeWhile 操作停止了事件流。
這時(shí)祠够,我們?cè)冱c(diǎn)擊界面上的任何按鈕都沒有任何反應(yīng)了。
現(xiàn)在我們可以把這個(gè)定時(shí)器想象成一個(gè) 5 秒倒計(jì)時(shí)器止剖,那我們的需求來了落君,現(xiàn)在的倒計(jì)時(shí)器是一次性的(除非刷新頁(yè)面),如何能讓它在一次倒計(jì)時(shí)完成后恢復(fù)到起始狀態(tài)呢绎速?這時(shí),repeat 操作符閃亮登場(chǎng)了纹冤。
下面只把變化的代碼貼出來:
const subscription = timer$
.pipe(
takeWhile(data => data < 5),
repeat()
)
.subscribe(
x => console.log(x),
err => console.log(err),
() => console.log("complete")
);
我們?cè)?takeWhile 操作符下面添加了 repeat 操作符,這時(shí)的效果如下圖:
倒計(jì)時(shí)清零的需求完成了雁歌。這時(shí)我們還發(fā)現(xiàn)知残,控制臺(tái)再也沒有輸出 complete ,這時(shí)因?yàn)槲覀儧]有給 repeat 傳入任何參數(shù),代表無限重復(fù)執(zhí)行印蔗。大家可以自己試試傳入了參數(shù)是什么效果丑勤。
下面要重點(diǎn)說明的是,使用 repeat 操作符的位置將影響它的行為法竞,這里交給讀者自己去嘗試,比如把 repeat 放在 takeWhile 的前面會(huì)是什么效果岔霸。使用 repeat 操作符的最佳實(shí)踐是放在離訂閱函數(shù)最近的位置。
接下來型宝,我們先來看看下面的代碼會(huì)有什么輸出:
const timer$ = time$.pipe(
switchMap(addOneOrReset),
startWith({ count: 0 }),
scan((acc, current) => current(acc)),
map(obj => obj.count),
tap(v => setTxt(v)),
);
timer$.subscribe(console.log)
timer$.subscribe(console.log)
我們訂閱了兩遍定時(shí)器流絮爷,控制臺(tái)輸出了兩遍 0 ,這合情合理坑夯,每個(gè)訂閱函數(shù)擁有獨(dú)立的定時(shí)器流。但假如我們想讓后來的訂閱函數(shù)永遠(yuǎn)得到的是最新內(nèi)容呢柜蜈?就像訂閱雜志,你得到雜志是從你訂閱的時(shí)間以后的雜志隶垮,總不能把以前 20 年的雜志都給你吧秘噪?share 操作符可以幫你完成這個(gè)需求岁疼。我們只需在定時(shí)器流的最后加入 share缆娃,那么第二個(gè) subscribe 函數(shù)將不會(huì)打印輸出瑰排,這個(gè)就交給大家自己試試吧。
const timer$ = time$.pipe(
switchMap(addOneOrReset),
startWith({ count: 0 }),
scan((acc, current) => current(acc)),
map(obj => obj.count),
tap(v => setTxt(v)),
share(),// <--- 這里
);
如有任何問題崇渗,更多內(nèi)容請(qǐng)關(guān)注微信公眾號(hào)“讀一讀我”(只給你實(shí)際工作用得上的干貨)。