学习《Build your own React》第三章《Concurrent Mode》时,碰到一个有趣的浏览器API-->>window.requestIdleCallback(callback)
,它会利用浏览器的空闲时间执行callback
中的代码。
什么叫“浏览器的空闲时间”?
如同电影一样,网页是由浏览器一张张绘制出来的,一般浏览器的刷新频率是60Hz,那就说明,浏览器每秒要绘制60张页面,即60帧,帧与帧的间隙可以称为时间片,长度为1000/16
约等于16ms
。
如果一帧渲染完成的时间小于16ms
,那么这个时间片内就有空闲时间。
空闲时间会被浏览器用来执行window.requestIdleCallback(callback)
的回调函数。
参数
此API有两个参数:
参数1:callback
函数,存放需要调用的代码。
参数2:{timeout:时间值}
,表示等待超时的时间,即如果超过这个时间值还不执行callback
函数,callback
将会被强制执行。
callback函数
无法被执行,说明时间片内已经没有了空闲时间,此时强制执行callback
函数,会阻塞本次渲染,延长渲染时间,必然会对用户感知造成一定影响,如:卡顿、延迟等
callback
callback
函数有一个IdleDeadline
接口类型的参数,其实就是一个对象,内含两个属性:
didTimeout
,布尔值,表示任务是否超时。timeRemaining()
,表示当前时间片剩余的时间,可以理解为在当前时间片内还剩余多少时间可以利用。
取消回调
window.requestIdleCallback(callback)
会返回一个ID:
let handle = window.requestIdleCallback(callback);
该ID传入window.cancelIdleCallback()
可结束对应回调:
window.cancelIdleCallback(handle);
常规用法:work loop
function workLoop(deadline) {
/* 时间片是否耗尽的标志 */
let shouldYield = false;
/* 假如时间片没有被耗尽,则继续处理work */
while (!shouldYield) {
//TODO SOME WORK
/* 刷新标志 */
shouldYield = deadline.timeRemaining() < 1;
}
/* 递归设置callback */
requestIdleCallback(workLoop);
}
// 设置第一个callback
requestIdleCallback(workLoop);