2014-12-02 29 views
18

我無法設法在onload函數中同時獲得filereader的結果和一些參數。這是我的代碼:帶有結果和參數的FileReader onload

控制的HTML:

<input type="file" id="files_input" multiple/> 

JavaScript函數:

function openFiles(evt){ 
    var files = evt.target.files; 
    for (var i = 0; i < files.length; i++) { 
     var file=files[i]; 
     reader = new FileReader(); 
     reader.onload = function(){ 
      var data = $.csv.toArrays(this.result,{separator:'\t'}); 
     }; 
     reader.readAsText(file); 
    } 
    } 

添加事件:

files_input.addEventListener("change", openFiles, false); 

我使用filereader.result,在onload功能。如果我爲這個函數使用參數,比如文件,我不能再訪問結果。例如,我想在onload函數中使用file.name。如何解決這個問題?

+0

它用一個文件工作?嘗試創建不同的閱讀器,添加「var reader = new FileReader();」 – 2014-12-12 08:03:39

+0

使用一個簡單的規則:在閉包的開始聲明所有的局部變量。不要在'for','in'和其他類似的語句中聲明它們,因爲這些語句不會創建閉包,因此聲明的變量對語句而言不是本地的。這將幫助您確定何時需要創建額外的關閉。 – hon2a 2014-12-18 10:51:05

回答

28

嘗試在另一個函數中包裝你的onload函數。這裏的封閉讓你訪問的每個文件通過變量f依次進行處理:

function openFiles(evt){ 
    var files = evt.target.files; 

    for (var i = 0, len = files.length; i < len; i++) { 
     var file = files[i]; 

     var reader = new FileReader(); 

     reader.onload = (function(f) { 
      return function(e) { 
       // Here you can use `e.target.result` or `this.result` 
       // and `f.name`. 
      }; 
     })(file); 

     reader.readAsText(file); 
    } 
} 

爲什麼這裏需要一個封閉的討論,請參閱以下相關問題:

+2

如果瀏覽器有'FileReader',我認爲它支持forEach並綁定:)我認爲最好使用綁定來添加文件到onload回調 – Pinal 2014-12-12 09:15:45

+0

@Pinal這是一個很好的建議。我不會更新我的答案來包含這些內容,因爲我想保持我的答案儘可能接近OP提供的代碼,只更改必要的內容(引入閉包),但最好了解這些功能。 – Chris 2014-12-12 09:18:09

+0

類似的徒勞,在生產代碼中,我試圖將FileReader代碼移動到它自己的循環中調用的命名函數中。閉包行爲會像預期的那樣,並有助於打破代碼。這就是說給出的例子更適合於展示技術解決方案。 – Hargobind 2014-12-18 22:11:18

5

您應該在'onload'處理程序中使用閉包。 實施例:http://jsfiddle.net/2bjt7Lon/

reader.onload = (function (file) { // here we save variable 'file' in closure 
    return function (e) { // return handler function for 'onload' event 
     var data = this.result; // do some thing with data 
    } 
})(file); 
-1

作爲可變文件是的範圍內,則可以使用文件可變不經過它的功能。

function openFiles(evt){ 
 
    var files = evt.target.files; 
 
    for (var i = 0; i < files.length; i++) { 
 
      var file=files[i];  
 
      reader = new FileReader(); 
 
      reader.onload = function(){ 
 
       alert(file.name); 
 
       alert(this.result); 
 
      }; 
 
     reader.readAsText(file); 
 
    } 
 
    } 
 

 
files_input.addEventListener("change", openFiles, false);
<input type="file" id="files_input" multiple/>

+0

'文件'將在循環中更改...您的示例工作不正確 – Pinal 2014-12-12 09:14:15

+0

這不起作用,請參閱http://stackoverflow.com/q/1451009/623518爲什麼。 – Chris 2014-12-12 09:16:34

+0

謝謝是啊:)但是,當我通過顯示每個文件的名稱和內容進行測試時,這似乎工作。運行上面的代碼片段。我想我錯過了會看到的東西。 – Banu 2014-12-12 10:06:08

3

事件處理是異步的,因此,他們拿起所有的封閉的局部變量(即封閉)的最新值。爲了特定的本地變量綁定到時,你需要按照用戶上面,或者你可以看看這個工作示例建議代碼: -

http://jsfiddle.net/sahilbatla/hjk3u2ee/

function openFiles(evt){ 
    var files = evt.target.files; 
    for (var i = 0; i < files.length; i++) { 
    var file=files[i]; 
    reader = new FileReader(); 
    reader.onload = (function(file){ 
     return function() { 
     console.log(file) 
     } 
    })(file); 
    reader.readAsText(file); 
    } 
} 

#Using jQuery document ready 
$(function() { 
    files_input.addEventListener("change", openFiles, false); 
}); 
+0

這不太對。你應該給'reader.onload'分配一個函數。您所調用的IIFE不會返回任何內容,因此一旦讀取器啓動了加載事件,代碼就不會運行。 – Chris 2014-12-18 21:51:05

+0

我不明白爲什麼返回一個函數很重要,當這段代碼只會在onload事件上運行並且綁定文件時 – sahilbathla 2014-12-19 04:35:01

+0

當前,函數'(function(file){console.log(file) })(file);''for'for'循環的每次迭代運行一次。它不會返回任何內容,因此對於循環的每個元素都使用'reader.onload = undefined'。因此,儘管你的'console.log'確實打印了正確的文件名,當'reader'激發它的'load'事件時,什麼都不會運行。 – Chris 2014-12-19 08:17:39