如何做一个准确的定时器

 定时器在前端的编程中 非常普遍, 最经常看到的是 抢购倒计时, 时钟 , 定时循环,。。。
但是浏览器的多线程模式 && js的单线程执行逻辑, 注定setTimeout、 setInterval  是非准确的 。
举例 一个完善的定时任务逻辑 是这样, Js 代码执行到 setTimeout 异步任务 ,会把异步任务推送到定时器线程, 定时器线程开始倒计时, 当倒计时结束,会把异步任务中的 回调函数 ,压入到js  的宏任务队列中,  此时 如果js 线程的执行栈中有大量的 耗时任务,显然会延迟事件循环 从宏任务队列中 取出回调函数到执行栈中执行.
那如何实现一个准确的定时器? 
HTML5 给出一个新的API   window.requestAnimationFrame  其本身 用来更好的渲染动画效果 ,
window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行 -------MDN 
但在大多数遵循W3C建议的浏览器中,回调函数执行次数通常与浏览器屏幕刷新次数相匹配,通常是60次每秒。
 下面可以实现我们自己的 setTimeout 

function  mySetTimeOut(callBack , interval) {
  let timer={value:undefined} ; 
  const now = Date.now ;
  let startTime = now();
  let endTime = startTime ;
  const loop =  () => {
    timer.value = window.requestAnimationFrame(loop);
    endTime = now () ;
   if (endTime-startTime >= interval){
       endTime = startTime = now();
       cancelAnimationFrame(timer.timer);
       callBack&&callBack(timer);
    }
}
    timer.value = window.requestAnimationFrame(loop); 
     console.log('timer',timer);
     return timer ; 
  }

function clearMySettimeout (timer){
   timer&&timer.value &&cancelAnimationFrame(timer.value) ;
}

  const timer= mySetTimeOut(()=>{},1000); 


如上我们也可以  模拟setInterval

function  mySetInterval(callBack , interval) {
  let timer={value:undefined} ; 
  const now = Date.now ;
  let startTime = now();
  let endTime = startTime ;
  const loop =  () => {
    timer.value = window.requestAnimationFrame(loop);
    endTime = now () ;
   if (endTime-startTime >= interval){
       endTime = startTime = now();
       callBack&&callBack();
    }
}
    timer.value = window.requestAnimationFrame(loop); 
     return timer ; 
  }

function clearMysetInterval (timer){
   timer&&timer.value &&cancelAnimationFrame(timer.value) ;
}

  const timer= mySetInterval(()=>{},1000); 




 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值