前后端数据顺序不一致?原来是原生方法Object.keys()的锅

2,401 阅读2分钟

问题背景

客服反馈后端上送的原始数据与报表展示的数据顺序不一致,例如:

原始数据
日期数据
20211123xxxx
20211120xxxx
20211128xxxx
20211130xxxx
20211210xxxx
20211203xxxx
实际表格展示
日期数据
20211120xxxx
20211123xxxx
20211128xxxx
20211130xxxx
20211203xxxx
20211210xxxx

这是表格成精了?会自动排序了?于是,我又看了下其他的表格

原始数据
类型数据
老师最美
医生最美
程序员最美
真实数据
类型数据
老师最美
医生最美
程序员最美

这不一样?这表格还看数下饭?诶,好像只有key是数字的时候会出现自动排序的行为,几经验证,确实如此!

问题排查

出了线上Bug还能咋办,当然是翻代码,查commit-log,突然发现在经过一次数据处理的时候,数组顺序变了!

问题定位

const column0Array = Object.keys(column0Map).map((val) => {
      // 处理逻辑
      {
        ...
      }
      arr.push(column0Map[val]);
      });

这里column0Map存储的是“每个日期下的信息”,like:

{
    20211203:{...},
    20211130:{...},
    20211128:{...},
    20211210:{...},
    ...
}

大概做的事情是,需要根据column的key按照顺序存到一个数组,但是!问题来了,这里的Object.keys()竟然偷偷地进行排序了!离谱?

验证猜想

image.png

问题原因

integer properties are sorted, others appear in creation order. —— 《现代 JavaScript 教程》

解释:在key为Number时,会被排序先,其他情况按照原始顺序

解决方案

1.维护一个原有key的arr,保证顺序,like:

    const keysArr = [20211203,20211130,20211128,20211210];
    keysArr.forEach(()=>{...})

2.改变数据结构为数组,like:

    const keysArr = [{key:20211203,value:{...}},...];
    keysArr.forEach(()=>{...})

总结

对象的遍历是不保证顺序的,对于需要保证顺序的数据,可以转化为数组先,就是多一个key的事~