递归这么一改,速度竟提升100多倍

197 阅读2分钟

这一切还要从生产环境上客户导入了5000多个部门说起。所以当部门有5000多个的时候,页面出现了明显的卡顿现象。

由于部门是vuex中全局使用的一个数据,所以在首页加载时就会进行加载,而首页数据又需要等待部门处理完后再加载。于是当首页部门数据较多的时候出现了长时间的等待。

通过chrome浏览器调试发现耗时最大的是一个dealTree的方法,什么,我写的代码居然有问题?

1CBD82EE887F7A441165EE7833A39DC1.gif

找到了相关的代码:

export function getTreeData(list = []) {
  console.time('getTreeData')
  const firstDep = list.sort((a, b) => a.parentId - b.parentId)[0] || {}
  const tree = list.filter(d => d.depId === firstDep.depId || 0)
  // 递归设置子级部门
  function setChildren(item, list) {
    const children = list.filter(i => i.parentId === item.depId)
    if (children.length > 0) {
      children.map(c => {
        setChildren(c, list)
      })
      item.children = children
    }
  }
  tree.map(item => {
    setChildren(item, list)
  })
  console.timeEnd('getTreeData')
  // console.log('------firstDepId', firstDep, list, tree)
  return tree
}

数据结构如下:

data = [
    {depId: 1, name: "一级", parentId: 0},
    {depId: 2, name: "二级", parentId: 1},
    {depId: 3, name: "三级", parentId: 2},
    ...
]

某个客户的数据如下: image.png

这特么是我写的代码?

image.png

这特么5000多条数据循环那么多次,不卡才怪!

569CF056CA31EAF9236BB17A1A746E29.gif

找到问题了,接下来开始优化,既然是一个平级的树结构,且通过parentId可以区分每个部门的子部门集合,那就用个Set或者Object把所有的部门分好组存储起来,然后通过属性读取相应的子部门即可,通过属性读取的速度比数组的循环是快很多的。

新的方法代码如下:

export function getTreeData2(list = []) {
  console.time('getTreeData2')
  const childMap = {}
  const parentIdSet = new Set()
  // 首次遍历将部门根据parentId分好组
  for (let i = 0; i < list.length; i++) {
    const item = list[i]
    parentIdSet.add(item.parentId)
    if (childMap[item.parentId]) childMap[item.parentId].push(item)
    else childMap[item.parentId] = [item]
  }
  // 将parentId排序
  const topDepId = Array.from(parentIdSet).sort((a, b) => a - b)[0]
  const tree = childMap[topDepId] || []
  function setDepChildren(dep) {
    const children = childMap[dep.depId] || []
    if (children.length > 0) {
      children.map(c => {
        setDepChildren(c)
      })
      dep.children = children
    }
  }
  tree.map(item => {
    setDepChildren(item)
  })
  console.timeEnd('getTreeData2')
  return tree
}

再让我们看一下这两个方法处理数据的对比,以下是点击执行20次的效果对比点这里看对比

image.png

不错,改完之后,首页加载终于顺畅了很多

E21A1A7124E7A4CC1C63D7FED84433F8.gif

总结: 写代码的时候一直很少注重性能,更多关注业务实现,有时候业务功能是实现了,没想到给后面埋了坑。不过吃一堑,长一智。记录下来,与小伙伴门共勉。

image.png