跳到主要内容

定时器

setTimeout 与 setInterval 有什么区别?​

  • setTimeout(callback, delay?, ...args): 延迟 delay 毫秒后执行一次, 返回定时器 ID;
  • setInterval(callback, delay?, ...args): 每间隔 delay 毫秒重复执行, 返回定时器 ID;
  • 取消: 分别用 clearTimeout(id) 与 clearInterval(id);
  • 执行归属: 回调作为宏任务入队, 具体时机见 单线程与事件循环;

定时器有哪些精度与调度局限?​

  • 精度: 时间精度无法保证, 通常有约 6ms 偏差;
  • 累积误差: setTimeout 的每次回调都会叠加前一次的耗时;
  • 任务跳过: setInterval 在上一次回调未执行完时可能跳过或叠加;
  • 规避: 需要严格间隔时用 setTimeout 递归调度代替 setInterval;

如何用两者互相模拟?​

  • setTimeout 实现 setInterval: 每次回调结束后再排下一次, 避免累积误差;
function mySetInterval(fn, delay) {
let timer = null;
const interval = () => {
fn();
timer = setTimeout(interval, delay);
};
timer = setTimeout(interval, delay);
return { cancel: () => clearTimeout(timer) };
}
  • setInterval 实现 setTimeout: 第一次触发时先清除自身再执行回调;
function mySetTimeout(fn, time) {
const timer = setInterval(() => {
clearInterval(timer);
fn();
}, time);
return { cancel: () => clearInterval(timer) };
}