requestIdleCallback/requestAnimationFrame 区别
# 01. requestIdleCallback
window.requestIdleCallback只有当系统有空闲时间时才会执行,若一直没有空闲时间则一直会等待,有一个options可选timeout超时取消,意思是当等待时间超过设定时间时就取消该任务
var handle = window.requestIdleCallback(callback[, options])
- callback:回调,即空闲时需要执行的任务,该回调函数接收一个IdleDeadline对象作为入参。其中IdleDeadline对象包含:
- didTimeout,布尔值,表示任务是否超时,结合 timeRemaining 使用。
- timeRemaining(),表示当前帧剩余的时间,也可理解为留给任务的时间还有多少。
- options:目前 options 只有一个参数 timeout。表示超过这个时间后,如果任务还没执行,则强制执行,不必等待空闲。
# 02. requestAnimationFrame(func)
每次都会执行,类似于setInterval只不过不用传延时,requestAnimationFrame采用系统时间间隔,保持最佳绘制效率,不会因为间隔时间过短,造成过度绘制,增加开销;也不会因为间隔时间太长,使用动画卡顿不流畅,让各种网页动画效果能够有一个统一的刷新机制,从而节省系统资源,提高系统性能,改善视觉效果。
特点 requestAnimationFrame会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率 在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的CPU、GPU和内存使用量 requestAnimationFrame是由浏览器专门为动画提供的API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了CPU开销
requestAnimationFrame的回调会在每一帧确定执行,属于高优先级任务,而requestIdleCallback的回调则不一定,属于低优先级任务。
基于浏览器的 requestIdleCallbac
k和requestAnimationFrame
两个API。
# 03. FPS(屏幕刷新率)
目前大多数设备的屏幕刷新率为 60 次/秒,每个帧的预算时间是16.66 毫秒 (1秒/60),1s 60帧,所以每一帧分到的时间是 1000/60 ≈ 16 ms。所以我们书写代码时力求不让一帧的工作量超过 16ms。
# 04. 了解每一帧
每个帧的开头包括样式计算、布局和绘制,JavaScript执行 Javascript引擎和页面渲染引擎在同一个渲染线程,GUI渲染和Javascript执行两者是互斥的,如果某个任务执行时间过长,浏览器会推迟渲染。
我们所看到的网页,都是浏览器一帧一帧绘制出来的,通常认为FPS为60的时候是比较流畅的,而FPS为个位数的时候就属于用户可以感知到的卡顿了,那么在一帧里面浏览器都要做哪些事情呢,如下所示:
requestAnimationFrame
回调函数会在绘制之前执行,requestIdleCallback
是在绘制之后执行。
假如某一帧里面要执行的任务不多,在不到16ms(1000/60)的时间内就完成了上述任务的话,那么这一帧就会有一定的空闲时间,这段时间就恰好可以用来执行requestIdleCallback
的回调
由于requestIdleCallback利用的是帧的空闲时间,所以就有可能出现浏览器一直处于繁忙状态,导致回调一直无法执行,这其实也并不是我们期望的结果,那么这种情况我们就需要在调用requestIdleCallback的时候传入第二个配置参数timeout了
requestIdleCallback(myNonEssentialWork, { timeout: 2000 });