阿里前端面试题:requestAnimationFrame实现类似setInterval的计时器

使用requestAnimationFrame实现类似setInterval的计时器

阅读 4.4k
评论
    2 个回答
    • 9k

    供参考,没有实现字符串功能,反正也不推荐使用。

    function setInterval2 (cb, delay, ...args) {
      // 记录所有正在运行的 interval 用于撤销
      let pool = window[Symbol.for('IntervalPool')]
      if (!pool) {
        pool = {}
        window[Symbol.for('IntervalPool')] = pool
      }
    
      // interval 最低 10ms,虽然每 frame 至少得 16ms
      delay = delay >= 10 ? delay : 10
      // interval id
      let ticket = Date.now()
      // 每次 interval 开始时间
      let startTime = ticket
      pool[ticket] = true
      loop()
      return ticket
    
      function loop () {
        if (!pool[ticket]) { return }
        const now = Date.now()
        if (now - startTime >= delay) {
          startTime = now
          cb(...args)
        }
        requestAnimationFrame(loop)
      }
    }
    
    function clearInterval2 (ticket) {
      let pool = window[Symbol.for('IntervalPool')]
      if (pool && pool[ticket]) {
        delete pool[ticket]
      }
    }
      • 12.4k
      function a(callback){
             requestAnimationFrame(function(){
                 //你的代码
                 callback && callback()
                 a()
             })
      }

      需要注意requestAnimationFrame的浏览器兼容性问题

      window.requestAnimationFrame = window.requestAnimationFrame || 
      window.webkitRequestAnimationFrame || 
      window.mozRequestAnimationFrame || 
      window.msRequestAnimationFrame || 
      window.oRequestAnimationFrame || 
      function (callback) {
          //为了使setTimteout的尽可能的接近每秒60帧的效果
          window.setTimeout(callback, 1000 / 60);
      };
          
      window.cancelAnimationFrame = window.cancelAnimationFrame || 
      Window.webkitCancelAnimationFrame || 
      window.mozCancelAnimationFrame || 
      window.msCancelAnimationFrame || 
      window.oCancelAnimationFrame || 
      function (id) {
          //为了使setTimteout的尽可能的接近每秒60帧的效果
          window.clearTimeout(id);
      }
        撰写回答

        登录后参与交流、获取后续更新提醒