微任务链式派生阻塞渲染

测试前两天提给我一个bug,点击一个按钮后页面会卡顿很久,然后才能出现弹窗。

我自己试了一下,点击按钮后,果然整个页面陷入了完全的卡顿,过了一会后弹窗出现,但此时操作页面同样会卡顿,一看就是js执行阻塞了渲染。

我又点击了其他数据同样位置的按钮,此时却一点都不卡顿。

可以推测应该是数据量太大导致处理函数的执行时间过长阻塞了渲染。

数据处理优化

于是找到处理函数,发现其中对列表数据进行了循环,又在循环中在一个大的字典表做字典匹配

ini 复制代码
// 示例代码
async function buildOptions(list) {
    for (let i = 0; i < list.length; i++) {
        const dictList = await getDict(config.dicType);
    }
}
​
async getDict(dicType) {
  let list: DicItem[] = [];
  if (!this.dictionaryList.length) {
    list = await this.getDictAll();
  } else {
    list = this.dictionaryList;
  }
  return list.filter(o => o.id == dicType);
}

由于是大数据的循环套循环,所以只要将字典表做一次循环变为map,就可以让效率提升。

kotlin 复制代码
async getDict(dicType) {
  if (!this.dictionaryList.length) {
    await this.getDictAll();
  }
  return this.dictionaryMap.get(dicType);
}

改好,再次点击按钮,熟悉卡顿、熟悉的掉帧,完全没有效果。

我老老实实的打开performance,查看一下这地方的点击前后的性能分析,发现点击按钮后执行的时间来到了3秒,其中大部分时间都在执行微任务。

我再看处理函数的代码,突然明白了。

同一事件循环中大量微任务阻塞

因为循环中使用了await,当dictionaryList中有值的时候,await创建的Promise会在本轮宏任务中立刻resolve,这时候后续的代码会作为微任务进入到微任务队列中。等执行该微任务的时候,下一次的循环依然会产生新的微任务,也就是 执行微任务=>微任务生成微任务=>执行微任务 这样一个过程直到循环结束。而所有微任务都在同一个宏任务内连续执行,于是浏览器渲染被阻塞。

知道了原因,改正就简单了,只要先执行一次带有await的方法,然后通过同步函数获取就可以了

javascript 复制代码
async function buildOptions(list) {
    await getDict('')
    for (let i = 0; i < list.length; i++) {
        const dictList = getDictSync(config.dicType);
    }
}
// 同步获取字典
function getDictSync(dicType) {
    return this.dictionaryMap.get(dicType) || [];
}

再次查看这个地方的性能分析,总耗时已经降下来了,来到了100ms

关键点: 循环内对同步函数用 await,每个 await 都把下一次循环推迟到微任务队列,前一个微任务执行完又产生下一个微任务,所有微任务连续执行不中断,直到循环结束,浏览器才有机会渲染。

相关推荐
广州灵眸科技有限公司12 小时前
瑞芯微(EASY EAI)RV1126B 千兆以太网电路
服务器·前端·人工智能·python·深度学习
梦想的旅途212 小时前
基于 RPA 自动化技术的外部群主动消息推送实现指南
前端·自动化·rpa
jiayong2312 小时前
前端面试题库 - React框架篇
前端·javascript·react.js
ttwuai12 小时前
XYGo Admin 国际化实战:Vue3 中后台多语言方案详解
前端·javascript·vue.js·vue
IT_陈寒12 小时前
React状态更新后视图不刷新?我差点以为是灵异事件
前端·人工智能·后端
Csvn12 小时前
JS 技巧:设计模式(下)- 策略、装饰器、代理
前端
一颗小青松12 小时前
uniapp 集成友盟并且上传页面路径
前端·vue.js·uni-app
周淳APP12 小时前
微前端核心沙箱机制深度解析:从iframe到乾坤沙箱
前端·学习·iframe·微前端·qiankun·前端架构
JarvanMo12 小时前
Android View 相关工具包终于成为了历史
前端
2501_9400417412 小时前
应用构建:前端复杂交互与数据可视化的进阶之路
前端·信息可视化