頁面不可見時,例如切換瀏覽器頁簽、最小化瀏覽器,暫停所有定時器;頁面顯示時,再啟動定時器。 ...
需求:
頁面不可見時,例如切換瀏覽器頁簽、最小化瀏覽器,暫停所有定時器;頁面顯示時,再啟動定時器。
一個解決方案如下:
const uuid = (() => {
let no = 0;
return () => no++;
})();
const originSetInterval = window.setInterval;
const originClearInterval = window.clearInterval;
const timers = [];
const startTimers = () =>
timers.forEach(t => {
t.originIntervalId = originSetInterval(
t.fn,
t.ms
);
});
const stopTimers = () =>
timers.forEach(t => {
originClearInterval(t.originIntervalId);
});
document.addEventListener(
"visibilitychange",
() =>
document.visibilityState === "visible"
? startTimers()
: stopTimers()
);
window.setInterval = (fn, ms) => {
const originIntervalId =
document.visibilityState === "visible"
? originSetInterval(fn, ms)
: undefined;
const id = uuid();
timers.push({
fn,
ms,
originIntervalId,
id
});
return id;
};
window.clearInterval = id => {
const t = timers.find(t => t.id === id);
originClearInterval(t.originIntervalId);
timers.splice(timers.indexOf(t), 1);
};
覆寫 setInterval
和 clearInterval
,不用改已有代碼,所有定時器就都能自動啟停。
但我不推薦在項目中這麼做,寧願麻煩點,寫個 setSmartInterval
,全局替換 setInterval
。原因有很多,例如:
- 可能影響第三方庫
- 沒法再用原生的
setInterval
- 新人培訓成本增加
- ……
其中,我最看重的是:這麼做導致 代碼行為出人意料。當一個東西和經驗認知不一樣時,使用它要付出更多的思考。每次用 setInterval
,都會想一下它和原生的區別。看起來是小事,卻會打斷你的思路。“Don't make me think”對於代碼設計同樣重要。