使用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);
使用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) })
首先,浏览器的定时器都不是精确执行的,如果setInterval里面的代码复杂的话,他同样不会在5s的时间里执行5次
其次,使用setTimeout模拟setInterval是为了解决上述缺陷,但它不能解决所有问题
最后,使用requestAnimationFrame模拟setInterval还不如使用setTimeout呢,因为requestAnimationFrame是动画帧,更不准确
如果你是要执行五次的话,那你可以使用计数的方式