【每日一题】为什么使用 setTimeout 实现 setInterval?

前端印记

共 2090字,需浏览 5分钟

 · 2021-09-02

人生苦短,总需要一点仪式感。比如学前端~

分析

setInterval 的作用是每隔一段指定时间执行一个函数,但是这个执行不是真的到了时间立即执行,它真正的作用是每隔一段时间将事件加入事件队列中,只有当目前的执行栈为空的时候,才能去事件队列中取出事件执行。

所以可能会出现这样的情况:若当前执行栈执行的时间很长,导致事件队列里边积累多个定时器加入的事件,当执行栈结束的时候,这些事件会依次执行,因此可能就不能实现“到间隔一段时间执行”的效果

针对 setInterval 的这个缺点,我们可以使用 setTimeout 递归调用来模拟 setInterval,这样我们就能确保实现“一个事件结束了、才触发下一个定时器事件”的效果,以解决了 setInterval 的问题。

模拟实现

接下来我们使用 setTimeout 模拟实现 setInterval,思路是使用递归函数,不断地执行 setTimeout 从而达到 setInterval 的效果。

简单实现

代码实现

function mySetInterval(fn, interval{
  // 设置递归函数,模拟定时器执行。
  function callback({
    fn();
    setTimeout(callback, interval);
  }
  // 启动定时器
  setTimeout(callback, interval);
}

执行测试

var i = 0

mySetInterval(() => {
  i++;
  console.log(i, '测试打印')
}, 1000);
测试结果

进阶版:控制是否继续执行

function mySetInterval(fn, interval{
  // 控制器,控制定时器是否继续执行
  var timer = {
    flagtrue,
  };

  // 设置递归函数,模拟定时器执行。
  function callback({
    if (timer.flag) { // 判断是否继续执行
      fn();
      setTimeout(callback, interval);
    }
  }
  // 启动定时器
  setTimeout(callback, interval);
  // 返回控制器
  return timer;
}

// 使用
let timer = mySetInterval(() => {
  console.log(123)
}, 1000)
setTimeout(() => {
  timer.flag = false
}, 4000)
测试结果

END
愿你历尽千帆,归来仍是少年。


让我们一起携手同走前端路!

关注公众号回复【加群】即可

● 工作中常见页面布局的n种实现方法

● 三栏响应式布局(左右固宽中间自适应)的5种方法

● 两栏自适应布局的n种实现方法汇总

● 工作中常见的两栏布局案例及分析

● 垂直居中布局的一百种实现方式

● 常用九宫格布局的几大方法汇总

● 为什么操作DOM会影响WEB应用的性能?

● 移动端滚动穿透的6种解决方案

● Vue + TypeScript 踩坑总结

浏览 36
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报