关于requestIdleCallback API的简单记录

743 阅读2分钟

学习《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);

统计数据定时上报

参考:MDN文档博客