多个setInterval叠加问题怎么解决?掌握这几点轻松应对

吉云

今天搞个东西,遇到点关于 `setInterval` 的小麻烦,记录一下省得以后再踩坑。

是这么回事,我当时在做一个页面,需要同时更新好几个地方的数据。比如说,一个地方要显示个实时时间,另一个地方,隔几秒钟就要去后台看看有没有新消息。我一开始图省事,也没多想,心说这不就俩定时器嘛简单。

直接上手

多个setInterval叠加问题怎么解决?掌握这几点轻松应对

我就直接在代码里写两个 `setInterval`。一个设1秒,更新时间;另一个设比如5秒,去请求数据。

刚开始跑起来,看着还行,时间在一秒一秒地跳,数据看着也在更新。心里还挺美,觉得挺顺利。

发现问题

但是跑一段时间,尤其是我切到别的页面再切回来的时候,怪事就发生。那个时间跳得好像越来越快?有时候甚至感觉一秒跳好几下。然后那个请求数据的,我一看网络请求记录,嚯,好家伙,密密麻麻的,请求频率明显比我设定的5秒要快得多,有时候甚至一秒发好几次!

这时候我就感觉不对劲,页面也变得有点卡顿。我就琢磨,这咋回事?明明设定好的时间间隔,怎么就乱套。

排查过程

多个setInterval叠加问题怎么解决?掌握这几点轻松应对

我就开始检查代码。一开始怀疑是不是逻辑写错,导致函数执行好几次。看半天,逻辑 вроде бы ( вроде бы means "seemingly" or "apparently" in Russian, used here colloquially like "kinda") 没啥大问题。

后来我尝试着在定时器函数里面加点打印信息,每次执行都输出点东西。结果不看不知道,一看吓一跳。每次我离开页面再回来(我用的是那种单页应用,页面切换是组件的卸载和重新加载),控制台里打印的信息就多一份!这说明说明之前的 `setInterval` 没停掉,新的又启动!

好家伙,等于说我每次回来,都新加一个定时器在跑,原来的还在那儿傻跑。这不就叠加嘛怪不得越来越快,请求越来越多,页面越来越卡。

  • 第一次进来:1个时间定时器,1个数据定时器。
  • 切走再回来:变成2个时间定时器,2个数据定时器。
  • 多个setInterval叠加问题怎么解决?掌握这几点轻松应对

  • 再切走再回来:变成3个时间定时器,3个数据定时器...

这谁受得。

解决办法

找到问题就好办。我想起来 `setInterval` 这东西是会返回一个ID的,可以用 `clearInterval` 来清除它。

关键点来:

多个setInterval叠加问题怎么解决?掌握这几点轻松应对

必须在组件卸载或者下次准备启动新的定时器之前,把上一个定时器给清除掉。

具体做法就是:

  1. 用一个变量(比如挂在组件实例上,或者用个全局点的变量,看情况)来保存 `setInterval` 返回的ID。
  2. 在组件卸载的生命周期钩子(比如 React 的 `useEffect` 的清理函数,或者 Vue 的 `beforeDestroy`/`unmounted`)里面,调用 `clearInterval(保存的ID)`。
  3. 或者,如果是在同一个组件内重复设置定时器,那就在每次设置新的 `setInterval` 之前,先判断一下那个保存ID的变量是不是有值,有的话就先 `clearInterval` 清掉旧的,再设置新的。
  4. 多个setInterval叠加问题怎么解决?掌握这几点轻松应对

比如像这样(伪代码示意一下):

let timerId = null;

function startMyTimer() {
  // 先清旧的
  if (timerId) {

多个setInterval叠加问题怎么解决?掌握这几点轻松应对

    clearInterval(timerId);
  }
  // 再设新的
  timerId = setInterval(() => {
    // ...干活...
  }, 1000);

多个setInterval叠加问题怎么解决?掌握这几点轻松应对

// 在不需要的时候,比如组件销毁时
function cleanup() {
  if (timerId) {
    clearInterval(timerId);
  }

多个setInterval叠加问题怎么解决?掌握这几点轻松应对

效果

把这些都改好之后,再测试。果然利索!不管我怎么切换页面,回来之后定时器都按预期的频率在跑,不多不少,页面也流畅。

总结一下就是: 用 `setInterval` 千万要记得擦屁股,不用的时候或者要重新设置的时候,一定得用 `clearInterval` 把之前的给清掉,不然它就一直在后台跑,越积越多,迟早出问题。算是给自己提个醒。

免责声明:由于无法甄别是否为投稿用户创作以及文章的准确性,本站尊重并保护知识产权,根据《信息网络传播权保护条例》,如我们转载的作品侵犯了您的权利,请您通知我们,请将本侵权页面网址发送邮件到qingge@88.com,深感抱歉,我们会做删除处理。

目录[+]