一、文章内容
- 时间分片
- 宏任务
- 微任务
- 前置内容
- 实现时间分片
二、时间切片
什么是时间切片?通过字面意思我们不难理解时间切片就是将时间分成多个片段进行一一渲染数据,时间切片是个抽象的问题,我们可能会想到JavaScript中window自带的setTimeout的延迟函数或者是 window.requestAnimationFrame通过这俩函数可以帮助我们进行时间切割.帮助我们加载大量数据.
三、宏任务须知
- setInterval与setTimeout所在的线程
- 定时任务并不是由JS引擎计时的,是由定时触发线程来计时的
- 计时完毕后,通知事件触发线程
浏览器为了能够使 宏任务
和 DOM任务
有序的进行,会在一个 宏任务
执行结果后,在下一个 宏任务
执行前, GUI渲染线程
开始工作,对页面进行渲染。
四、微任务须知
我们已经知道 宏任务
结束后,会执行渲染,然后执行下一个 宏任务
, 而微任务可以理解成在当前 宏任务
执行后立即执行的任务。
也就是说,当 宏任务
执行完,会在渲染前,将执行期间所产生的所有 微任务
都执行完。
五、前置内容
1.getElementById通过id名获取标签对象进行dom操作.
2.Math.min,返回多个参数中值最小的元素.
3.createElement创建dom元素的函数.
4.appendChild添加dom元素.
5.requestAnimationFrame,setTimeout/setInterval 的显著缺陷就是设定的时间并不精确,它们只是在设定的时间后将相应任务添加到任务队列中,而任务队列中如果还有前面的任务尚未执行完毕,那么后添加的任务就必须等待,这个等待的时间造成了原本设定的动画时间间隔不准。requestAnimationFrame的到来就是解决这个问题的 ,它采用的是系统时间间隔(约16.7ms),保持最佳绘制效果与效率,使各种网页动画有一个统一的刷新机制,从而节省系统资源,提高系统性能。
将上述提出的五个函数弄懂接下来就可以学习时间切片了.
六、实战环节
<ul id="container"></ul>
<script>
let ul = document.getElementById('container');
let total = 100000;
let once = 20;
let page = total/once
let index = 0;
function loop(curTotal){if(curTotal <= 0){return false;}let pageCount = Math.min(curTotal , once);window.requestAnimationFrame(function(){for(let i = 0; i < pageCount; i++){let li = document.createElement('li');li.innerText = ~~(Math.random() * total)ul.appendChild(li)}loop(curTotal - pageCount)})
}
loop(total);
</script>
代码解释;在第五部分须知函数弄懂后,跟着我的思路简单学习一下实现时间分片的核心思想.第一行是html框架,剩下的都是JavaScript代码.
let ul 就是创建一个无序列表dom点.然后total是一共假设生成的个数,once就是一次需要加载的个数,page就是一共total的数据需要多少页存储.loop函数是核心我们采用的是递归思路一直让自己调用自己知道没有数据加载.
可以看到在最后一行我们调用了loop传入了一个参数total是数据总数.
loop函数解读进入函数首先判断是否继续执行如果没有加载项就不渲染了.反正继续渲染,接下来通过Math.min找到最小值,如果加载到最后一部分然后数据只剩下10条我我们就需要判断到底是目前的条数还是once的条数!!!然后就是requestAnimationFrame用来优化拖动太快留下白影未加载的白屏的,然后循环添加li然后添加到ul里,就这么简单.然后去运行一下时间分片的demo吧.
七、总结
通过今天这一篇文章明白了时间分片是如何工作的以后只需要模仿写一段就可以达到处理大量数据了,不懂的地方欢迎留言.