遇到一个需求:页面不可见时,例如切换浏览器页签 或 最小化浏览器时,暂停所有定时器;页面显示时,再开启定时器。
一个解决方案如下:
const originalSetInterval = window.setInterval;
const originalClearInterval = window.clearInterval;
const timers = [];
document.addEventListener("visibilitychange", () => {
if (document.visibilityState === "visible") {
startTimers();
} else {
stopTimers();
}
});
window.setInterval = (fn, ms) => {
const originalIntervalId =
document.visibilityState === "visible"
? originalSetInterval(fn, ms)
: undefined;
const id = uuid();
timers.push({
fn,
ms,
originalIntervalId,
id
});
return id;
};
window.clearInterval = id => {
const t = timers.find(t => t.id === id);
originalClearInterval(t.originalIntervalId);
timers.splice(timers.indexOf(t), 1);
};
覆写 window.setInterval
和 window.clearInterval
,不用改已有代码,所有定时器就都能自动起停。
但我不推荐在项目中这么做,宁愿麻烦点,写个 setSmartInterval
,全局替换 setInterval
。
原因有很多,例如:
- 是否影响第三方库?
- 真的要用原来的
setInterval
怎么办? - 新人上手的成本
- ……
其中,我最看重原因是:这么做导致代码行为出人意料。
当一个东西和经验认知不一样时,使用它要付出更多的思考。
每次用 setInterval
,都会想一下它和原生的区别。看起来是小事,却能打断你的思路。
“Don‘t Make Me Think” 对于代码设计同样重要。