未捕获的DOMException:无法执行' readAsDataURL' on' FileReader':对象已经忙于读取Blob。(...)

时间:2016-10-31 18:46:04

标签: javascript

过去6个小时我正在研究这个问题,我无法弄清楚这一点。

我正在尝试创建一个网站,我在其中选择图像文件夹,然后在我的文档中显示它们。我得到第一个要显示的图像,然后在我的控制台中出现以下错误。

未捕获的DOMException:无法执行' readAsDataURL' on' FileReader':对象已经忙于阅读Blob。(...)

我认为问题是由于我的for循环引起的,因为filereader是异步的。但是我需要循环遍历整个数组,所以我做错了什么?

我将文件("将检查以确保我以后只获得图像")加载到一个数组中,然后我一次读取一个文件。  在将代码分解为函数之前,我在一个函数中完成了所有操作,并且它可以工作!我包含了HTML +原始和当前的JS代码。 感谢您花时间看这个。

HTML

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Tiled Image Viewer</title>
    <script src="js/tiv.js"></script>
    <link rel="stylesheet" href="style.css">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

  </head>
  <body>

    <div id="main-wrap">
      <form name="uploadForm">

        <input id="images" type="file" webkitdirectory mozdirectory directory name="myFiles"
                   onchange="readAndShowFiles();" multiple/>

        <span id="list"></span>
      </form>

    </div>

  </body>
</html>

Javascript原文:

function readAndShowFiles() {
 var files = document.getElementById("images").files;
 for (var i = 0; i < files.length; i++) {
   var file = files[i];
   // Have to check that this is an image though
   // using the file.name TODO
   var reader = new FileReader();
   // Closure to capture the file information.
   reader.onload = (function(file) {
     return function(e) {
       // Render thumbnail.
       var span = document.createElement('span');
       span.innerHTML = ['<img src="', e.target.result,
       '" title="', escape(file.name), '">'].join('');
       document.getElementById('list').insertBefore(span, null);
     };
   })(file);
   // Read in the image file as a data URL.
   reader.readAsDataURL(file);
 }
}

Javascript Current:

function readAndShowFiles() {
    console.log("Checkpoint2"); //test
    var tiv = new tivAPI();
    var array = tiv.getLoadedImages();
    tiv.showLoadedImages(array);
}

function tivAPI(){
  var imagesarray = new Array();


    return{
      loadImages: function(){
        console.log("Loading Files"); //test
        var files = document.getElementById("images").files;
        for (var i = 0; i < files.length; i++) {
          var file = files[i];
          // Have to check that this is an image though
          // using the file.name TODO
        }
        console.log(files.length); //test
        return files;
      },
      getLoadedImages: function(){
        imagesarray = this.loadImages();
        console.log("Returning Files"); //test
        console.log(imagesarray.length);
        return imagesarray;
      },
      showLoadedImages: function(elem){
        console.log("Showing Files"); //test
        var files = elem;
        var reader = new FileReader();
        // Closure to capture the file information.
        for (var i = 0; i < files.length; i++) {
          var file = files[i];
          reader.onload = (function(file) {
            return function(e) {
              // Render thumbnail.
              var span = document.createElement('span');
               span.innerHTML = ['<img src="', e.target.result,
              '" title="', escape(file.name), '">'].join('');
              document.getElementById('list').insertBefore(span, null);
            };

          })(file);
        // Read in the image file as a data URL.
        reader.readAsDataURL(file);
        }
      }
    };
  }

2 个答案:

答案 0 :(得分:6)

你的代码使用同一个阅读器的原因是因为你使用相同的阅读器变量。
所谓的javascript是所有变量都被移到顶部所以你的解析代码看起来像这样

function readAndShowFiles() {
  var files = document.getElementById("images").files;
  var reader;
  var file;
  var i;

  for (i = 0; i < files.length; i++) {
    file = files[i];
    reader = new FileReader();
    reader.onload = (function(file) {
      return function(e) {
        var span = document.createElement('span');
        span.innerHTML = ['<img src="', e.target.result,
          '" title="', escape(file.name), '">'
        ].join('');
        document.getElementById('list').insertBefore(span, null);
      };
    })(file);
    reader.readAsDataURL(file);
  }
}

只需移动annonymes函数中的所有逻辑就可以避免它变得非常简单

function readAndShowFiles() {
  var files = document.getElementById("images").files;

  for (var i = 0; i < files.length; i++) {
    // Closure to capture the file information.
    (function(file) {
      var reader = new FileReader();
      reader.onload = function(e) {
        // Render thumbnail.
        var span = document.createElement('span');
        span.innerHTML = ['<img src="', e.target.result,
          '" title="', escape(file.name), '">'
        ].join('');
        document.getElementById('list').insertBefore(span, null);
      };
      // Read in the image file as a data URL.
      reader.readAsDataURL(file);
    })(files[i]);
  }
}

现在您正在为每个文件使用uniq阅读器。另请注意,如果您刚刚执行此操作可能会更简单

array.from(files).forEach(function(file) {
  // code
})

或者只是使用了let变量(这样每次都会使用不同的FileReader

function readAndShowFiles() {
  var files = document.getElementById("images").files;

  for (var i = 0; i < files.length; i++) {
    let file = files[i];
    let reader = new FileReader();
    reader.onload = function(e) {
      // Render thumbnail.
      var span = document.createElement('span');
      span.innerHTML = ['<img src="', e.target.result,
        '" title="', escape(file.name), '">'
      ].join('');
      document.getElementById('list').insertBefore(span, null);
    };
    // Read in the image file as a data URL.
    reader.readAsDataURL(file);
  }
}

使用es6可以更容易地编写for循环,从而减少2个变量

function readAndShowFiles() {
  var files = document.getElementById("images").files;

  for (let file of files) {
    let reader = new FileReader();
    reader.onload = function(e) {
      // Render thumbnail.
      var span = document.createElement('span');
      span.innerHTML = ['<img src="', e.target.result,
        '" title="', escape(file.name), '">'
      ].join('');
      document.getElementById('list').insertBefore(span, null);
    };
    // Read in the image file as a data URL.
    reader.readAsDataURL(file);
  }
}

但是如果你想要它非常容易,为什么不一起跳过FileReader所有功能并避免所有功能&amp;使用createObjectURL与URL.createObjectURL进行回调,您可以将文件保存到/从base64编译文件

function showFiles() {
  var files = document.getElementById("images").files;

  for (let file of files) {
    let img = new Image;
    img.src = URL.createObjectURL(file);
    img.title = file.name;

    document.getElementById('list').appendChild(img);
  }
}

答案 1 :(得分:2)

问题发生了,因为我试图为每个图像使用相同的阅读器。 将var reader = new FileReader();移动到循环(ShowLoadedImages函数)中,解决了问题并显示了它应该的所有图像。