最近在做思考总结,项目原来在做智能合同的项目关于文档比对导致页面卡断问题,项目组同事给了我一个切片编程的方案很棒,在此做个总结!
需求
源文档和修改后的文档,差异点存在近 5000+ 的差异点需要在两个文档上进行颜色标注,整个标注过程都是在进行 DOM 操作,做完后存在严重的页面卡死问题,甚至等待 5~8分钟才标注完成,甚至卡死!这个问题亟待解决优化!
分析
在事件循环机制中主线程需要全部执行完才会进行页面渲染,5000+ 的 DOM 操作严重阻塞了主线程,所以是不是可以给主线程让出空间,将dom操作任务放进宏任务队列,在下一次渲染之后继续执行DOM操作呢?
思路
1、执行主线程,DOM操作(先进行20次dom操作,剩余的任务放进setTimeout宏任务)
2、页面渲染,显示差异对比的颜色标注(上一次dom操作的结果)
3、执行宏任务中 20个 DOM 操作任务
4、页面渲染
5、重复 3、4
最后是结了这个方案,5000+ 的dom操作还是蛮顺滑的!最后我们讲讲时间切片思想
什么是时间切片
时间切片的核心思想是:如果任务不能在50毫秒内执行完,那么为了不阻塞主线程,这个任务应该让出主线程的控制权,使浏览器可以处理其他任务。让出控制权意味着停止执行当前任务,让浏览器去执行其他任务,随后再回来继续执行没有执行完的任务。
所以时间切片的目的是不阻塞主线程,而实现目的的技术手段是将一个长任务拆分成很多个不超过50ms的小任务分散在宏任务队列中执行。

上图可以看到主线程中有一个长任务,这个任务会阻塞主线程。使用时间切片将它切割成很多个小任务后,如下图所示。

可以看到现在的主线程有很多密密麻麻的小任务,我们将它放大后如下图所示。

可以看到每个小任务中间是有空隙的,代表着任务执行了一小段时间后,将让出主线程的控制权,让浏览器执行其他的任务。
使用时间切片的缺点是,任务运行的总时间变长了,这是因为它每处理完一个小任务后,主线程会空闲出来,并且在下一个小任务开始处理之前有一小段延迟。
但是为了避免卡死浏览器,这种取舍是很有必要的。
如何使用时间切片
目前发现有两种解决方案,不过起主体还是通过让出主线程的控制权
1、setTimeout
2、requestAnimationFrame
3、setTimeout + Generator
方案一:setTimeout
function request() {
let result = [];
for (let i = 0; i < 100000; i++) {
result.push({
index: i,
text: ~~(Math.random() * 100000000),
});
}
return Promise.resolve(result);
}
let ul = document.querySelector("#app");
request().then((res) => {
let total = res.length;
let once = 20;
let page = total / once;
let curIndex = 0;
function loop(curTotal, curIndex)

本文讲述了在智能合同项目中,面对大量DOM操作导致页面卡死的问题,通过引入时间切片技术,将5000+的差异标注任务分解为小任务,有效提升渲染效率,避免主线程阻塞。核心内容涉及setTimeout、requestAnimationFrame和Generator的使用,以确保高性能渲染并减少页面闪烁。
最低0.47元/天 解锁文章
1419

被折叠的 条评论
为什么被折叠?



