概念:
为什么是16.67毫秒:
这个根据浏览器刷新帧率来定,大多数浏览器的刷新帧率是60Hz,所以1/60 = 0.0166666... (秒)= 16.67(毫秒)
如果一个任务耗时很长,那么时间用完后会中断该任务吗?
不会中断该任务,一直到执行完毕为止,所以如果单个任务耗时很长,那么也会造成卡顿。
测试用例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title></title> </head> <body> </body> <script> function sleep(delay) { //在js里面实现睡眠功能 for (let start = Date.now(); Date.now() - start <= delay;) {} } //fiber 是把整个任务分成很多个小任务,每次执行一个任务 //执行完成后会看看有没有剩余时间,如果有继续执行下一个任务,如果没有就放弃执行,使用requestIdleCallback将控制权交还给浏览器 let requesqQueut = [ () => { console.log('第一个任务开始') sleep(20)//一帧16.67毫秒(1000/60帧),所以需要把控制权交给浏览器 console.log('第一个任务结束') }, () => { console.log('第二个任务开始') sleep(20) console.log('第二个任务结束') }, () => { console.log('第三个任务开始') sleep(20) console.log('第三个任务结束') }, () => { console.log('第四个任务开始') sleep(20) console.log('第四个任务结束') }, ] //告诉浏览器1000毫秒后,即使你没有空闲时间,也得帮我执行,因为我已经等不及了 window.requestIdleCallback(callBack, {timeOut: 1000}) //deadLine是一个对象,有两个属性 //timeRemaining() 返回此帧执行剩余时间 //didTimeout 此callBack是否超时 function callBack(deadLine) { console.log(`本帧的剩余时间为:${deadLine.timeRemaining()}`) //如果此帧=还有剩余时间 或 此时已经超时了 while ((deadLine.timeRemaining() > 0 || deadLine.didTimeout) && requesqQueut.length > 0) { performUnitOfQueueTask() } //说明还有没有执行完的任务 if (requesqQueut.length > 0) { window.requestIdleCallback(callBack, {timeout: 1000}) } } function performUnitOfQueueTask() { requesqQueut.shift()() } </script> </html>