JS如何优雅的处理大批量数据?

本文主要是针对JavaScript(以下简称JS)处理大批量数据时,产生性能问题的简要分析,以及如何优雅的演化提升性能的解决方案;

场景:假设有10W条数据量,需要相应业务处理并绑定渲染在html页面,如何一步一步的分析并优化 JS 的性能,提升数据处理速度;

假设我们需要处理的需求如下,从0到10W条数据通过ul>li的方式显示在html页面上:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>JS大批量数据渲染测试Demo</title>
</head>
<body>
    <!-- <ul id="container">
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>...</li>
        <li>10000</li>
    </ul> -->

    <ul id="container">

    </ul>

    <script type="text/javascript" src="../js/scheme1.js"> //依次修改后面演化的方案【scheme2.js】,【scheme3.js】,【scheme4.js】
</body>
</html>

我们该如何让 JS 优雅的处理这10W条数据呢?

1.常规方式 =>【一次性渲染】:scheme1.js

let now = Date.now();
const total = 100000; // 插入的数据总数
let oContainer = document.getElementById('container');
// DOM:document object model 文档对象模型
for (let i = 0; i < total; i++) {
     let oLi = document.createElement('li'); // 创建li元素
     oLi.innerHTML = i; //注意区分:innerHTML ,innerText  ??
     oContainer.appendChild(oLi);
}
console.log('js运行时间:' , Date.now() - now);
// 渲染页面      
setTimeout(()=>{
    console.log('总的运行时间:' , Date.now() - now);
}, 0);

测试浏览器:【QQ浏览器极速内核】

 测试结果:

2.【定时器分批加载】:scheme2.js

const total = 100000;
let oContainer = document.getElementById('container');
const once = 2000; // 一次插入的条数
const page = total / once; // 总的页数
const index = 0; // 数据的索引

function insert (curTotal, curIndex){
    if(curTotal <= 0){
        return; // 递归的出口
    }
    setTimeout(()=>{
        for(let i=0; i<once; i++){
            let oLi = document.createElement('li');
            oLi.innerHTML = curIndex + i;
            oContainer.appendChild(oLi);
         }
         // 递归的入口
         insert(curTotal - once, curIndex + once); //[curTotal - once]:剩余的条数,[curIndex + once]:开始的索引
    }, 0);
}

insert(total, index); //递归调用

测试结果:

3.告知浏览器动画处理 =》【window.requestAnimationFrame】:scheme3.js

const total = 100000;
let oContainer = document.getElementById('container');
const once = 2000; // 一次插入的条数
const page = total / once; // 总的页数
const index = 0; // 数据的索引

function insert (curTotal, curIndex){
    if(curTotal <= 0){
        return; // 递归的出口
    }
    window.requestAnimationFrame(()=>{
        for(let i=0; i<once; i++){
            let oLi = document.createElement('li');
            oLi.innerHTML = curIndex + i;
            oContainer.appendChild(oLi);
        }
        // 递归的入口
        insert(curTotal - once, curIndex + once); //[curTotal - once]:剩余的条数,[curIndex + once]:开始的索引
    });
}

insert(total, index); // 递归调用

测试结果:

4.文档片段化 =》【document.createDocumentFragment】:scheme4.js

const total = 100000;
let oContainer = document.getElementById('container');
const once = 2000; // 一次插入的条数
const page = total / once; // 总的页数
const index = 0; // 数据的索引

function insert (curTotal, curIndex){
    if(curTotal <= 0){
        return;// 递归的出口
    }
    window.requestAnimationFrame(()=>{
        let fragment = document.createDocumentFragment(); // 文档碎片
        for(let i=0; i<once; i++){
            let oLi = document.createElement('li');
            oLi.innerHTML = curIndex + i;
            // oContainer.appendChild(oLi);
            fragment.appendChild(oLi);
        }
        oContainer.appendChild(fragment);
        // 递归的入口
        insert(curTotal - once, curIndex + once); //[curTotal - once]:剩余的条数,[curIndex + once]:开始的索引
    });
}

insert(total, index); // 递归调用

测试结果:

备注:以上测试受浏览器(型号,版本)影响,电脑内存,硬件以及【FPS=》是图像领域中的定义,是指画面每秒传输帧数,通俗来讲就是指动画或视频的画面数】,大多数显示显示器60Hz;本人同一个浏览器每个方案测试三次,基本都有一定的时间偏差,以上只是个基本的参考。

总结:

a.浏览器是顺序解析,JS是阻塞加载,会阻塞DOM树或阻塞渲染树的构建;

b.JS中setTimeout()执行的时间并不唯一准确;

c.windows.requestAnimationFrame() =》告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画;

d.重排【Reflow】必定会引发重绘,但重绘【Repaint】不一定会引发重排;https://www.cnblogs.com/yadongliang/p/10677589.html

e.document.createDocumentFragment() =》他们是DOM节点,并不是主DOM树的一部分。通常的用例是创建文档片段,将元素附加到文档片段,然后将文档片段附加到DOM树。在DOM树中,文档片段被其所有的子元素所代替。因为文档片段存在于内存中,并不在DOM树中,所以将子元素插入到文档片段时不会引起页面回流(对元素位置和几何上的计算)。因此,使用文档片段通常会带来更好的性能。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章