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樹中,所以將子元素插入到文檔片段時不會引起頁面迴流(對元素位置和幾何上的計算)。因此,使用文檔片段通常會帶來更好的性能。

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