Ostrov Ostrov - 1 month ago 5
Javascript Question

How to improve performance when loading CSV file into html table with javascript and ajax?

Im using this code

$( document ).ready(function() {
$.ajax({
url: 'https://dl.dropboxusercontent.com/s/wuvqbsupfc27iaq/systemSK.csv',
dataType: 'text',
}).done(hovory);

function hovory(data) {
var promenna = data.replace(/\n/g,";").split(";");
var result = [];
for(var i = 0; i < promenna.length; i+=32) {
var line = [];
line.push(promenna[i+0]);
line.push(promenna[i+1]);
line.push(promenna[i+14]);
line.push(promenna[i+15]);
line.push(promenna[i+16]);
line.push(promenna[i+25]);
line.push(promenna[i+26]);
line.push(promenna[i+27]);
result.push(line);
}


for(var i = 0; i < result.length; i+=1){
var radek = '<tr>';
radek += '<td>' + result[i][0] + '</td>';
radek += '<td>' + result[i][1] + '</td>';
radek += '<td>' + result[i][2] + '</td>';
radek += '<td>' + result[i][3] + '</td>';
radek += '<td>' + result[i][4] + '</td>';
radek += '<td>' + result[i][5] + '</td>';
radek += '<td>' + result[i][6] + '</td>';
radek += '<td>' + result[i][7] + '</td>';
radek += '</tr>';
var theDiv = document.getElementById("tabulka");
theDiv.innerHTML += radek;
}
};
});


I basically load the csv from Dropbox, create array from it and appends table. It works, but its very slow look at my codepen http://codepen.io/anon/pen/XjOyYE?editors=1010

If you set at for(var i = 0; i < result.length; i+=1) i+= at 7 table appends immediately. If to 1, then takes some time until table appends.

Is there a way how to append my table quicker? What creates that delay?

Answer

Your major problem comes from constant DOM manipulation, you must avoid adding it every row once it is a very large amout of data, otherwize will result in a large amout of DOM operations which is very expensive. I reduced the time of the rendering loop just by moving the table outside the loop and then adding the entire table once from 4210.902ms to 36.266ms, as you can see, it's a huge difference.

Also, you can reduce the loops to only one, in this case, there is no need to use two loops. You can split the rows by line breaks (i.e. \n), and columns by semicolon (;) and build your table within the process.

UPDATE 1

By reusing the main loop I could reduce the hovory time from 229.830ms to 23.405ms.

Original:

ajax: 1713.042ms
promenna: 3.281ms
for1: 6.031ms
for html: 4240.323ms
hovory: 4251.732ms

After reduce DOM operations:

ajax: 2001.135ms
promenna: 4.595ms
for1: 2.395ms
for html: 19.575ms
hovory: 229.830ms

After reuse the main loop to render the html:

ajax: 658.290ms
hovory: 23.405ms

$( document ).ready(function() {
  console.time('ajax');
  $.ajax({
    url: 'https://dl.dropboxusercontent.com/s/wuvqbsupfc27iaq/systemSK.csv',
    dataType: 'text',
  }).done(function (data) {
    
    console.timeEnd('ajax');
    console.time('hovory');
    hovory(data);    
    console.timeEnd('hovory');
  });

  function hovory(data) {
    
    var rows = data.split('\n').map(function (row) {
      row = row.split(';');
      
      var radek = '<tr>';
      radek += '<td>' + row[0] + '</td>';
      radek += '<td>' + row[1] + '</td>';
      radek += '<td>' + row[14] + '</td>';
      radek += '<td>' + row[15] + '</td>';
      radek += '<td>' + row[16] + '</td>';
      radek += '<td>' + row[25] + '</td>';
      radek += '<td>' + row[26] + '</td>';
      radek += '<td>' + row[27] + '</td>';
      radek += '</tr>';
      
      return radek;
    }).join('');
    var theDiv = document.getElementById("tabulka");
    theDiv.innerHTML = rows;    
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<table id="tabulka"></table>

Comments