时间切片编程 timeslice

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

最近在做思考总结,项目原来在做智能合同的项目关于文档比对导致页面卡断问题,项目组同事给了我一个切片编程的方案很棒,在此做个总结!

需求

源文档和修改后的文档,差异点存在近 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) 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值