JavaScript for for file on files FileReader

时间:2017-07-10 13:04:24

标签: javascript for-loop filereader

问题是我的想法。有人能帮我吗? 在我的html文件的<script>标记中,我有:

window.ondragover = function(e){return false;}
window.ondragenter = function(e){return false;}
window.ondrop = function(e){
    var files = e.target.files || e.dataTransfer.files;
    for (var i = 0, file; file = files[i];i++){
        var img = document.createElement('img');
        img.height = 200;
        img.width = 200;
        img.style.background = 'grey';
        document.body.appendChild(img);
        var reader = new FileReader();
        reader.onload = function(){
            img.src = reader.result;
        }
        reader.readAsDataURL(file);
    }
    return false;
}

但是当我在浏览器上删除多个图像文件时,只有最后一个图像文件被加载并显示在最后一个img元素中,其他图像文件保持灰色。

1 个答案:

答案 0 :(得分:6)

正如@chazsolo所说:

  

有一种感觉这是由于你在循环中使用img。由于reader.onload是异步的,for循环已经完成,img指向最后一个

您可以在循环(let - MDN)中使用let代替var来解决此问题。这将为每个imgreader提供一个块范围,允许异步读取器方法仍然访问该特定循环运行的实际值。

window.ondragover = function(e){return false;}
window.ondragenter = function(e){return false;}
window.ondrop = function(e){
    var files = e.target.files || e.dataTransfer.files;
    debugger;
    for (var i = 0, file; file = files[i];i++){
        let img = document.createElement('img');
        img.height = 200;
        img.width = 200;
        img.style.background = 'grey';
        document.body.appendChild(img);
        let reader = new FileReader();
        reader.onload = function(){
            img.src = reader.result;
        }
        reader.readAsDataURL(file);
    }
    return false;
}

更新:var vs let

那么为什么var不能怀疑它? 我尝试用一​​些实际例子来解释letvar的区别。

  

变量声明,无论它们出现在何处,都会在任何声明之前处理   代码被执行。

这引出了以下示例(最后请注意错误,这是由剪切的插件产生的):

使用var 的声明

&#13;
&#13;
/**
In this example, 'a' is declared after it is used. This doesn't matter, as the 
declaration of 'a' will be processed before running the code. This means a is 
initialized with 'undefined' but is valid. Also the scope of a lies within the 
execution context, that's why it is even available outside of the loop. 
**/
console.log("---------");
console.log("Example Declaration var");
console.log("---------");
for (var i = 0; i < 2; i++) {
  console.log(a); // a is declared but undefined on the 1st run, afterwards it get redeclared and owns the value from the last run.
  var a = i;
}
console.log(a); // a is even available out here as still same execution context.
&#13;
&#13;
&#13; 我们看到,在a之前的a的每次重新声明都保留了。它不是一个新的&#34;实例&#34;。

那么如果我们在循环中使用异步函数会发生什么?

与var的异步功能

&#13;
&#13;
/**
This example shows you the effects, if you use a async function within a loop. 
As the loop will be executed way under 100 miliseconds (which is the time out 
of the async function), c will have the same value for all exections of the 
async mehtod, which is the value assigned by the last run of the loop.
**/
console.log("---------");
console.log("Example effects async var");
console.log("---------");
for (var i = 0; i < 2; i++) {
  var c = i;
  setTimeout(function() {
    console.log(c); //var does redeclare, therefor c will be modified by the next loop until the last loop.
  }, 100);
}
&#13;
&#13;
&#13;

确实,总是相同的输出(适应你的问题,总是相同的img元素和文件)

让我们看看let

发生了什么 使用

声明

&#13;
&#13;
/**
In this example, 'b' is declared after it is used with let. let will be processed 
during runtime. This means 'b' will not be declared when used. This is an invalid 
state. let will give a strict context within the loop. It will be not available 
outside. let has a similar behavior as a declaration in Java.
**/
console.log("---------");
console.log("Example Declaration let");
console.log("---------");
for (var i = 0; i < 2; i++) {
  try {
    console.log(b); //b is not declared yet => exception
  } catch (ex) {
    console.log("Exception in loop=" + ex);
  }
  let b = i;
  console.log("Now b is declared:"+b);
}
try {
  console.log(b); // b is not available out here as the scope of b is only the for loop. => exception
} catch (ex) {
  console.log("Exception outside loop=" + ex);
}
console.log("Done");
&#13;
&#13;
&#13; 抛出了许多异常,因为let具有更具体的范围。这导致更有意的编码。

最后,我们看到当我们在循环中使用let和异步函数时会发生什么。

使用 的异步功能

&#13;
&#13;
/**
This example shows you the effects, if you use a async function within a loop. 
As the loop will be executed way under 100 milliseconds (which is the time out 
of the async function). let declares a new variable for each run of the loop, 
which will be untouched by upcoming runs.
**/
console.log("---------");
console.log("Example effects async let");
console.log("---------");
for (var i = 0; i < 2; i++) {
  let d = i;
  setTimeout(function() {
    console.log(d); //let does not redeclare, therefor d will not be modified by the next loop
  }, 100);
}
&#13;
&#13;
&#13;

<强>结论

在您的示例中,您总是以最后分配的img元素和最后分配的file结束。您执行相同操作的次数与阵列中的文件相同,只是最后一个文件。