【问题标题】:HTML5 File API: onload too slowHTML5 文件 API:加载太慢
【发布时间】:2013-03-25 17:45:30
【问题描述】:

我是 JavaScript 和 jQuery 的新手,而 Google 没有给出答案。我正在写一个在线电子书阅读器。这是一个库的代码,用户可以在其中输入多个 epub 文件,相关信息(如作者)应显示在表格中。为此,我需要提取 ePub 文件。 jsZip library 完美运行。内容必须显示在动态创建的表格中(因为我不知道文件的数量)。

问题在于 for 循环是快速创建所有单元格,其中只有名称和文件大小,并且在 for 循环完成后 FileReader 的 onload 执行并将所有内容添加到最后一个单元格中。在这段代码中,alert("A") 发生的次数与在 alert("B") 发生之前输入的文件一样多。有什么方法可以让循环等到 FileReader 的加载完成?

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);

【问题讨论】:

  • 有什么原因不能将所有cell.appendChild(...) 语句移到onload 回调中?
  • 不,没有具体原因,但这不会解决问题,因为在调用 onload 函数之前单元格的值已更改。这可以通过创建一个临时变量来保存特定单元格来解决。使用 Ali Gangji 所说的功能很有效。
  • 太棒了。那么你应该接受 Alis 的回答。

标签: javascript html filereader


【解决方案1】:

您的问题是 onload 处理程序中使用的变量 cell 将引用分配给外循环中 cell 的最后一个值。您可以通过将文件处理放在一个单独的函数中来解决这个问题,该函数将创建它自己的范围。

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);
}

然后在外循环中可以调用:

read_zip_file(f, cell);

【讨论】:

  • 为 zip 创建一个单独的函数。隐式创建临时单元变量是解决方案,使用函数是最好的方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-30
  • 2019-01-19
  • 2018-04-05
  • 1970-01-01
  • 1970-01-01
  • 2019-05-01
  • 2023-03-27
相关资源
最近更新 更多