不要覆盖标准方法
需求:
页面不可见时,例如切换浏览器页签、最小化浏览器,暂停所有定时器;页面显示时,再启动定时器。
一个解决方案如下:
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
- 新人培训成本增加
- ……
其中,我最看重的是:这么做导致 代码行为出人意料。当一个东西和经验认知不一样时,使用它要付出更多的思考。「Don't make me think」对于代码设计同样重要。