由一篇文章引发的一系列前端知识学习

背景

偶然看到一篇文章,《前端大容量缓存方案-IndexedDB》-zhuanlan.zhihu.com/p/104536473 在了解IndexedDB过程中,发现了另外一篇文章zhuanlan.zhihu.com/p/95076534 在大佬的主页发现一篇阿里的面试坎坷之路,然后看到了相关的面试知识点www.zhihu.com/column/c_10... 其中讲到了很多知识点,觉得似曾相识,又说不出所以然,于是决定重新学习一遍

首先注意到了"时间切片",因为我们项目里目前也有因响应时间长,页面白屏,影响体验的问题

在了解时间切片的过程中,发现一篇文章zhuanlan.zhihu.com/p/111263128 文章底部,"高性能渲染十万条数据(时间分片)"---juejin.cn/post/684490... 发现了大佬。那么,就倒着学习吧。

菜鸟进阶

1.关于Event Loop、宏任务、微任务

CPU

进程

进程类似工厂的车间,进程之间相互独立,任一时刻,CPU总是运行一个进程,其他进程处于非运行状态。

线程

线程好比车间里的工人,一个进程可以包括多个线程,多个线程共享进程资源。

浏览器是多进程的,一个tab页对应一个进程。

浏览器包含的进程

  • 主进程
  • 第三方插件进程(每种类型的插件对应一个进程,使用时才会创建)
  • GPU进程(用于3D绘制)
  • 渲染进程,及浏览器内核(负责页面渲染,脚本执行,事件处理)

渲染进程包含的线程

  • GUI渲染线程

    • 负责渲染页面,布局和绘制
    • 页面需要重绘和回流时,该线程就会执行
    • 与js引擎线程互斥,防止渲染结果不可预期
  • JS引擎线程

    • 负责处理解析和执行javascript脚本程序
    • 只有一个JS引擎线程(单线程)
    • 与GUI渲染线程互斥,防止渲染结果不可预期(一个渲染,一个改,要是同时进行,岂不是矛盾了)
  • 事件触发线程

    • 用来控制事件循环(鼠标点击、setTimeout、ajax等)
    • 当事件满足触发条件时,将事件放入到JS引擎所在的执行队列中
  • 定时触发器线程

    • setInterval与setTimeout所在的线程
    • 定时任务并不是由JS引擎计时的,是由定时触发线程来计时的
    • 计时完毕后,通知事件触发线程
  • 异步http请求线程

    • 浏览器有一个单独的线程用于处理AJAX请求
    • 当请求完成时,若有回调函数,通知事件触发线程

Event Loop

不管是setTimeout/setIntervalXHR/fetch代码,在这些代码执行时, 本身是同步任务,而其中的回调函数才是异步任务。

宏任务 浏览器为了能够使宏任务DOM任务有序的进行,会在一个宏任务执行结果后,在下一个宏任务执行前,GUI渲染线程开始工作,对页面进行渲染。

主代码块,setTimeout,setInterval等,都属于宏任

微任务

宏任务结束后,会执行渲染,然后执行下一个宏任务,而微任务可以理解成在当前宏任务执行后立即执行的任务

当宏任务执行完,会在渲染前,将执行期间所产生的所有微任务都执行完。

Promise, process.nextTick,属于微任务。

ini 复制代码
`document.body.style = 'background:blue'

console.log(1);

Promise.resolve().then(()=>{ 

  console.log(2);

  document.body.style = 'background:black'

});

console.log(3);`

控制台输出1,3,2,页面的背景色直接变成黑色,没有经过蓝色的阶段,因为执行完微任务才会渲染:

宏任务->微任务->渲染

javascript 复制代码
setTimeout(() => {

    console.log(1)

    Promise.resolve(3).then(data => console.log(data))

}, 0)

setTimeout(() => { console.log(2) }, 0) // print : 1 3 2`

除主代码块外,共有两个宏任务,其中第一个宏任务执行中,输出1,并且创建了微任务队列,所以在下一个宏任务队列执行前,先执行微任务,微任务执行中,输出3,微任务执行后,执行下一次宏任务,执行总输出2。

总结:

先执行一个宏任务,执行过程中,有微任务,则先添加到微任务队列,继续执行当前宏任务,执行完宏任务后,执行所有微任务队列,然后渲染,最后开启下一次宏任务。

链接地址: juejin.cn/post/684490...

2.高性能渲染十万条数据(时间分片)

运行结果如下图:

看完第一部分的Event Loop就不难理解这块了,第一个console打印的是第一次宏任务执行的时间,第二个console打印的是第二个宏任务执行的结束时间,中间的时间差就是渲染的时间

因此我们知道对于大量数据渲染的时候,JS运算不是性能瓶颈,性能瓶颈在于渲染阶段。

优化

方案1: 使用setTimeout分批渲染,明显渲染速度有提升,但是滚动时会出现白屏现象。

该方案的缺点

(1)setTimeout的执行时间并不是设置的时间,只有主线程执行完,才会去检查事件队列中的任务是否需要执行,实际执行事件可能会比其设定的时间晚。

(2)刷新频率受屏幕分辨率和屏幕尺寸的影响,不同设备的刷新频率可能会不同,而setTimeout只能设置一个固定的时间间隔,这个时间不一定和屏幕的刷新时间相同。

方案2:使用requestAnimationFrame

与setTimeout相比,requestAnimationFrame最大的优势是由系统决定回调函数的执行时机。如果屏幕刷新频率是60Hz,那么回调函数就每16.7ms执行一次,如果刷新频率是75Hz,那么这个间隔时间就变成了1000/75=13.3ms。

页面加载速度很快,并且滚动的时候,没有出现闪烁丢帧的现象。

经过以上学习,我对时间分片的理解是,对于大量渲染的任务,性能卡在渲染上,那就把大的宏任务分成若干宏任务,缩短了每个宏任务的渲染时间,这个时间间隔如果和屏幕分辨率保持一致,在视觉上就不会出现白屏卡顿的现象。

相关推荐
崔庆才丨静觅2 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60613 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了3 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅3 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅4 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅4 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment4 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅4 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊5 小时前
jwt介绍
前端
爱敲代码的小鱼5 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax