HTML5 API: loading too slow

I am new to jQuery JavaScript and Google does not produce an answer. I am writing an online ebook reader. This is the code for the library where the user can enter several epub files, and the corresponding information (for example, the author) should be displayed in the table. To do this, I need to extract the ePub file. jsZip library works fine. The content should be displayed in a dynamically created table (since I do not know the number of files).

The problem is that the for loops should quickly create all cells with only the name and size in them, and after the forload loop ends, the FileReader executes and adds all the contents to the very last cell. In this code, a warning ("A") occurs as many times as it does with files that were entered before the warning ("B"). Is there a way that I can make loops wait until FileReader finishes loading?

function handleFileSelect(evt) {
var files = evt.target.files;
var rows = Math.ceil(files.length/3);
var a = 0;
var root = document.getElementById('mainTable');
var tab=document.createElement('table');
tab.style.textAlign = "center";
var row, cell;
var tbo=document.createElement('tbody');
for(var i  = 0; i != rows; i++)
{
  row=document.createElement('tr');
  for(var j = 0; (j < 3);j++)
  {
   cell = document.createElement('td');
   cell.height = "300px";
   cell.width = "300px"
   if(a <indexes.length)
   {
        var f = files[a];
        var str = f.name;
        str = str.substring(0, str.length - 5);
        str = "File Name: " + str;
        cell.appendChild(document.createTextNode(str));
        cell.appendChild(document.createElement('br'));
        str = "File Size: " + Math.round(f.size/1024) + " KB";
        cell.appendChild(document.createTextNode(str));
        cell.appendChild(document.createElement('br'));
        var reader = new FileReader();
        reader.onload = (function(theFile) 
        {
          return function(e) 
          {
              alert("B");
              var zip = new JSZip(e.target.result);
              $.each(zip.files, function (index, zipEntry) 
              {
                  cell.appendChild(document.createTextNode(zipEntry.name));
                  cell.appendChild(document.createElement('br'));
                  //row.appendChild(cell);
              });
          }
        })(f);
        reader.readAsArrayBuffer(f);
        alert("A");
        a++;
    }
    row.appendChild(cell);
  }
  tbo.appendChild(row);
}
tab.appendChild(tbo);
root.appendChild(tab);              
}
document.getElementById('files').addEventListener('change', handleFileSelect, false);
+5
source share
1 answer

Your problem is that the variable cell used in your onload handler will refer to the last value assigned to the cell in the outer loop. You can get around this by putting file processing in a separate function that will create its own scope.

function read_zip_file(f, cell) {
    var reader = new FileReader();
    reader.onload = (function(theFile) 
    {
      return function(e) 
      {
          alert("B");
          var zip = new JSZip(e.target.result);
          $.each(zip.files, function (index, zipEntry) 
          {
              cell.appendChild(document.createTextNode(zipEntry.name));
              cell.appendChild(document.createElement('br'));
              //row.appendChild(cell);
          });
      }
    })(f);
    reader.readAsArrayBuffer(f);
}

Then, within the outer loop, you can call:

read_zip_file(f, cell);
+1
source

All Articles