使用setTimeout代替setInterval方案得到的结果不准确??

  1. 使用setTimeout代替setInterval

    function myInterval(fn, a) {
             this.fn = fn;
             this.a = a;
             this.timerId = -1;
             this.start = () => {
                 this.timerId = setTimeout(() => {
                     fn();
                     //这样才能实现间隔计时
                     this.start();
                 }, this.a);
             };
             this.stop = () => {
                 clearTimeout(this.timerId);
             };
         }
         //for test 5000内持续性计时
         var test = new myInterval(
             () => {
                 console.log("123");//打印四次"123"???
             },
             1000
         );
         test.start();
         setTimeout(() => {
             test.stop();
         }, 5000);
  2. 使用requestAnimationFrame模拟setTimeout

    class Interval {
         constructor() {
             this.intervalTimer = null;
         }
         setInterval(cb, interval) {
             let now = Date.now;
             let stime = now();
             let etime = stime;
             let loop = () => {
                 this.intervalTimer = requestAnimationFrame(loop)
                 etime = now()
                 if (etime - stime >= interval) {
                     // 重新计时
                     stime = now();
                     etime = stime;
                     // 执行cb
                     cb();
                 }
             }
             // 开始执行
             this.intervalTimer = requestAnimationFrame(loop)
             return this.intervalTimer
         }
         clearInterval() {
             cancelAnimationFrame(this.intervalTimer)
         }
     }
     let i = new Interval()
     i.setInterval(() => {
         console.log('inter')//依旧打印4次'inter'???
     }, 1000)
     setTimeout(() => {
         i.clearInterval()
     }, 5000)

    上面两种方法模拟得到的setInterval都不是很准确,因为原始的setInterval在5s内每秒打印一次,那就会打印5次

    let timer = setInterval(() => {
     console.log('i')// 打印五次????
    }, 1000)
    setTimeout(() => {
     clearInterval(timer)
    })
阅读 1.6k
1 个回答

首先,浏览器的定时器都不是精确执行的,如果setInterval里面的代码复杂的话,他同样不会在5s的时间里执行5次

其次,使用setTimeout模拟setInterval是为了解决上述缺陷,但它不能解决所有问题

最后,使用requestAnimationFrame模拟setInterval还不如使用setTimeout呢,因为requestAnimationFrame是动画帧,更不准确


如果你是要执行五次的话,那你可以使用计数的方式

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题