簡體   English   中英

解析大型CSV文件時,jQuery崩潰

[英]Jquery crashes while parsing large csv file

我有這個jquery函數,我在一個教程網站上發現了該函數,它接受一個csv文件輸入並將其制成表格。 我嘗試輸入一個較大的csv文件(10,000KB),但我的瀏覽器崩潰了。 我看到有一個名為papa的解析器庫來處理此問題,但是還有其他方法可以防止瀏覽器在執行此操作時崩潰嗎?

以下是相關代碼:

 $("#upload").bind("click", function () {

        var regex = /^([a-zA-Z0-9\s_\\.\-:])+(.csv|.txt)$/;
        if (regex.test($("#fileUpload").val().toLowerCase())) {
                            var reader = new FileReader();
                reader.onload = function (e) {
                    var table = $("<table id='mytable' class='table table-striped table-bordered'/>");
                    var rows = e.target.result.split("\n");
                    text1=e.target.result;
                    var csvString = $.trim(text1);
                    var csvRows    = csvString.split(/\n/);
                    var csvHeaders = csvRows.shift().split(';');
                    var headerstr=String(csvHeaders);
                    var count = (headerstr.match(/,/g) || []).length+1;
                    for (var i = 0; i < rows.length; i++) {
                        var row = $("<tr />");
                        var cells = rows[i].split(",");
                        for (var j = 0; j < count; j++) {

                            if(cells[j]){
                            var cell = $("<td/>");

                            cell.html(cells[j]);
                            }
                            else{
                            var cell = $("<td class='info'/>");
                            cell.html("empty");}
                            row.append(cell);

                        }
                        table.append(row);

                    }


                    $("#dvCSV").html('');
                    $("#dvCSV").append(table);
                }

    });

如何在不使瀏覽器崩潰的情況下實現此功能? 提前致謝。

解決此問題有兩個大問題:

1)CSV解析器。 爸爸解析很棒。 它具有對worker的支持,並且是流解析器-處理大型文件的唯一方法。

2)顯示數據的方式。 僅輸出表中的每一行將不起作用。 我兩次崩潰了PC,試圖提出一個可行的解決方案。 這樣做的唯一方法以及基本上任何處理大文件的系統都使用的方法是使用虛擬化列表。 我最終使用了這個 這很簡單,代碼也很容易理解。

這是我的JS:

$("#fUpload").bind("change", function(evt) {
    var bigFile = evt.target.files[0];
    var rows = [];
    Papa.parse(bigFile, {
        delimiter: ",",
        newline: "\n",
        header: false,
        dynamicTyping: false,
        worker: false,
        chunk: function(results) {
            rows.concat(rows, results.data);
        },
        complete: function() {
            var list = new VirtualList({
              h: 300,
              itemHeight: 30,
              totalRows: rows.length,
              generatorFn: function(row) {
                  var el = document.createElement("div");
                  el.innerHTML = "<p>ITEM " + row + ' -> ' + rows[row].join(' - ') + "</p>";
                  return el;
              }
            });
            document.body.appendChild(list.container)
        }
    });
});

HTML包含以下輸入: <input type="file" id="fUpload" />

我如何配置Papa:

  • delimiternewline :如果允許它嘗試檢測它們,它將失敗或花費更長的時間;

  • worker :這將產生一個worker進程。 這會比較慢, 但是將使UI保持響應狀態(UI線程將無法執行任何工作)。 您可能需要在生產中將其設置為true (由於瀏覽器跨域安全協議,這在JSFiddle上將不起作用!);

  • chunk :不是解析過的每一行都有一個回調,而是有一個更大的行集。 這樣更快。

虛擬列表配置是默認配置。

你可以在這里運行它。

我測試了一個9.4 MB的CSV文件,其中每行重復包含1,Foo,100

這是相同的,但是使用表來輸出數據,並向VirtualList的totalRows添加了-1以補償實際長度。

我建議您使用console.log('...')來確定它的鎖定/中斷位置,也許在第一個變量(行,csvString)中是因為大小。 因此,您可以知道在哪里進行攻擊。

如果不在before循環塊中,那么我認為在這種情況下使用jquery過於昂貴,因此請嘗試直接使用DOM方法(至少在循環內部):

$("#upload").bind("click", function () {
    var regex = /^([a-zA-Z0-9\s_\\.\-:])+(.csv|.txt)$/;
    if (regex.test($("#fileUpload").val().toLowerCase())) {
                        var reader = new FileReader();
            reader.onload = function (e) {
                var table = $("<table id='mytable' class='table table-striped table-bordered'/>");
                var rows = e.target.result.split("\n");
                text1=e.target.result;
                var csvString = $.trim(text1);
                var csvRows    = csvString.split(/\n/);
                var csvHeaders = csvRows.shift().split(';');
                var headerstr=String(csvHeaders);
                var count = (headerstr.match(/,/g) || []).length+1;
                for (var i = 0; i < rows.length; i++) {
                    var row = document.createElement("tr");
                    var cells = rows[i].split(",");
                    for (var j = 0; j < count; j++) {
                        var cell = document.createElement("td");
                        if(cells[j]){

                        cell.appendChild(document.createTextNode(cells[j]));
                        }
                        else{
                            cell.setAttribute('class','info');
                            cell.appendChild(document.createTextNode("empty"));
                        }
                        row.appendChild(cell);

                    }
                    table.append(row);

                }


                $("#dvCSV").html('');
                $("#dvCSV").append(table);
            }

});

我沒有測試此代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM