Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Day370:为什么使用 setTimeout 实现 setInterval?怎么模拟? #1204

Open
Genzhen opened this issue Aug 20, 2021 · 0 comments
Open
Labels
JavaScript teach_tag

Comments

@Genzhen
Copy link
Collaborator

Genzhen commented Aug 20, 2021

每日一题会在下午四点在交流群集中讨论,五点小程序中更新答案
欢迎大家在下方发表自己的优质见解

二维码加载失败可点击 小程序二维码

扫描下方二维码,收藏关注,及时获取答案以及详细解析,同时可解锁800+道前端面试题。


参考分析

setInterval 的作用是每隔一段指定时间执行一个函数,但是这个执行不是真的到了时间立即执行,它真正的作用是每隔一段时间将事件加入事件队列中去,只有当当前的执行栈为空的时候,才能去从事件队列中取出事件执行。所以可能会出现这样的情况,就是当前执行栈执行的时间很长,导致事件队列里边积累多个定时器加入的事件,当执行栈结束的时候,这些事件会依次执行,因此就不能到间隔一段时间执行的效果。

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

参考实现

思路是使用递归函数,不断地去执行 setTimeout 从而达到 setInterval 的效果

  • 简单实现
function mySetInterval(fn, timeout) {
  function interval() {
    fn();
    setTimeout(interval, timeout);
  }
  setTimeout(interval, timeout);
}
  • 还可以加个控制器,控制是否继续执行
function mySetInterval(fn, timeout) {
  // 控制器,控制定时器是否继续执行
  var timer = {
    flag: true,
  };

  // 设置递归函数,模拟定时器执行。
  function interval() {
    if (timer.flag) {
      fn();
      setTimeout(interval, timeout);
    }
  }
  // 启动定时器
  setTimeout(interval, timeout);
  // 返回控制器
  return timer;
}
@Genzhen Genzhen added the JavaScript teach_tag label Aug 20, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
JavaScript teach_tag
Projects
None yet
Development

No branches or pull requests

1 participant