温故而知新:javascript中requestAnimationFrame与setTimeout

115 阅读1分钟

前言

两者都是网页中定时器的操作,表示间隔多长时间执行回调函数,但是在间隔时长处理上是截然不同的,这就导致了他们使用的场景有所不同。

requestAnimationFrame

window.requestAnimationFrame()是一个全局的方法,它告诉浏览器你需要执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数来更新动画,该方法只需传入一个回调函数作为参数,不需要动画间隔时长。

requestAnimationFrame()方法自身只会调用一次,如果希望实现动画效果,则需要使用递归的方式循环调用

 window.onload = function () {
    const box = document.querySelector('.box')
    let handlerId = null
    let left = 0
    const setAnimation = () => {
      if (left > 500) {
        // 取消动画执行
        cancelAnimationFrame(handlerId)
        return
      }
      handlerId = requestAnimationFrame(() => {
        box.style.marginLeft = `${left++}px`
        setAnimation()
      })
    }
    setAnimation()
  }
  • requestAnimationFrame动画执行的频率与显示器的刷新频率一致,显示器刷新频率大部分的是60Hz(每秒刷新60次), 算下来是每次间隔17ms左右,所以用来作为动画效果是非常合适的,不会出现卡顿,而setTimeout大概率会出现卡顿

  • requestAnimationFrame动画效果在当前浏览器标签被切换或者隐藏时,动画会停止工作,这样做的目的是节省性能以及电池的消耗

setTimeout

setTimout与requsetAnimationFrame用法类似,只是setTimeout定时器的间隔时间是手动设置的,由于js单线程原因,就会导致一个问题,回调函数的执行可能不会在间隔时间到来之际被执行,如果主线程繁忙,大概率会被延后执行,是不准确的, 这样就会导致动画的卡顿。

const timer = setTimeout(() => {
    // to do...
    console.log('hi')
}, 2000)
clearTimeout(timer)