一、setTimeout
- 基于任务长度分块: 将长度位100000的长任务,分成每一块为1000的短任务,每次执行完之后,返还主线程的控制权,查看是主线程栈是否有优先级更高的任务(如响应用户输入);
- 基于时间片长度分块: 利用浏览器的performance API,可以获取当前任务已经执行的时间;基于这个机制,可以将长任务分成用户自定义时间长度的短任务,进行调度;
二、performance
借助chrome浏览器的开发者工具的api实现时间分片
javascript
1 | const timeSplit = async () => { |
三、requestIdleCallback
- 对于 requestAnimationFrame(callback),浏览器会在刷新周期末尾调用其注册的callback;而对于requestIdleCallback(callback),浏览器会在刷新周期的空闲时段调用其callback。
- 他俩和 setTimeout、setInterval 不同的地方,setTimeout(callback, time) 和 setInterval(callback, time),只要未被注销都能够按规定的时间间隔(time)重复执行。但是 setTimeout 和 setInterval 的时间间隔设置不当会导致丢帧,造成动画卡顿。
- requestIdleCallback 的存在使得前端开发人员可以将优先级较低耗时又很多的任务注册为 requestIdleCallback 的 callback,等待浏览器空闲的时候再执行,类似一个后台程序,以免阻塞浏览器主线程造成卡顿。但是如果浏览器长期被其他高优先级的任务占据主线程,会导致 requestIdleCallback 注册的 callback 无法执行,所以 requestIdleCallback 还提供了一个 timeout 参数。plaintext
1
requestIdleCallback(callback, timeout)
javascript1
2
3
4
5
6
7
8
9
10
11
12function unImportWork(deadline) {
while (deadline.timeRemaining() && tasksNum > 0) {
tasksNum--
}
console.log(`执行了${100000 - tasksNum + 1}个任务`)
if (tasksNum > 0) { // 在未来的帧中继续执行
requestIdleCallback(unImportWork)
}
}
var tasksNum = 100000
requestIdleCallback(unImportWork)