为什么 requestAnimationFrame 比 setTimeout 更适合做动画?

1、requestAnimationFrame 和 setTimeout 的执行时机
    例:
console.log('主代码块')
requestAnimationFrame(() => {
    console.log('requestAnimationFrame')  // 此处比 setTimeout 先执行
})
setTimeout(()=>{console.log('setTimeout')},0)
    requestAnimationFrame 和 setTimeout 都属于宏任务,但影响两者执行时机的因素不同
    requestAnimationFrame 是在浏览器下一次渲染之前调用
    setTimeout 是在指定时间之后将回调添加到异步队列,等待同步任务完后再从异步队列中取出执行
    那么,为什么 requestAnimationFrame 会比 setTimeout 先执行呢
2、下一次渲染之前 是在什么时候
    大多数浏览器的渲染频率为60HZ,也就是一秒钟渲染60次左右,每次大约16.6ms
    浏览器在一帧内做的事情大致分为以下几点
    (1) 处理交互事件
    (2) 执行JS脚本
    (3) 开始帧
    (4) 执行 requestAnimationFrame 回调
    (5) 重新计算样式, 生成布局树, 生成渲染列表
    所以 requestAnimationFrame 的执行时机在重新计算样式之前,具体的执行时机由浏览器自行判定,当浏览器空闲时,反复执行 requestAnimationFrame 的间隔就是 16.6 ms左右,当浏览器繁忙时,处理一帧的时间可能会超过16.6ms,此时这个间隔会被拉长(可以视为丢帧)
    setTimeout 的执行时机收到同步任务的影响,若从异步队列中取出时,还有同步任务在执行,那么就会导致 setTimeout 的延迟执行,通常这个最小延迟为4ms(也有部分浏览器是10ms
3、setTimeout 比 requestAnimationFrame 更容易丢帧
    例:
let last = Date.now()
function render() {
    var i=0; 
    while(i<100000000){i++}; 
    let now = Date.now()
    console.log(now - last)
    last = now
    // setTimeout(()=>{
    //   render()
    // },16.6)
    requestAnimationFrame(() => {
        render()
    })
}
render()
    在此例中,分别尝试了 requestAnimationFrame 和 setTimeout 做 1亿次计算,通过结果比对,requestAnimationFrame 的执行间隔逐渐稳定在30ms左右,而 setTimeout 的执行间隔稳定在 50ms 左右,丢帧率差距明显
 4、丢帧是怎么产生的
    
全部评论

相关推荐

点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务