不要覆盖标准方法

需求:

页面不可见时,例如切换浏览器页签、最小化浏览器,暂停所有定时器;页面显示时,再启动定时器。


一个解决方案如下:

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);
};

覆写 setIntervalclearInterval,不用改已有代码,所有定时器就都能自动启停。


但我不推荐在项目中这么做,宁愿麻烦点,写个 setSmartInterval ,全局替换 setInterval。原因有很多,例如:

  • 可能影响第三方库
  • 没法再用原生的 setInterval
  • 新人培训成本增加
  • ……

其中,我最看重的是:这么做导致 代码行为出人意料。当一个东西和经验认知不一样时,使用它要付出更多的思考。「Don't make me think」对于代码设计同样重要。

posted @ 2020-03-19 18:15  apolis  阅读(319)  评论(0编辑  收藏  举报