2016-04-07 20 views
1

我試圖在使用javascript上傳之前將圖像加載到頁面以進行預覽。文件讀取器在javascript中執行多次

我已經以下代碼:

holder.onclick = function(event) { 

    function chooseFile(name) { 
     var chooser = $(name); 
     chooser.unbind('change'); 
     chooser.change(function(evt) { 

      function loadFile(file, callback) { 
       var reader = new FileReader(); 

       (reader.onload = function(file) { 

        console.log(f);  
        var output = document.createElement('input'); 
        output.type = 'image'; 
        output.classList.add('image-responsive'); 
        output.classList.add('col-xs-12'); 
        output.name = f; 
        output.id = f; 
        output.src = reader.result; 

        var x = document.getElementById('OrigName'); 
        x.appendChild(output); 

        return callback(output); 
       })(f = file.name); 

       reader.readAsDataURL(file); 
      } 

      for (var i = 0; i < evt.target.files.length; i++) { 
       console.log(i); 
       var file = evt.target.files[i]; 
       loadFile(file, function(output) { 
        // console.log(output); 
       }); 
      } 
     }); 
     chooser.trigger('click'); 
    } 
    chooseFile('#fileDialog'); 
} 

問題是,每當我加載圖像,reader.onload方法內執行代碼兩次,並在控制檯I 2倍的console.log(f)和2個錯誤的結果是'localhost/null未找到'。

當我刪除(f = file.name),腳本執行它應該是,但然後我沒有file.name變量裏面的讀者範圍。

編輯:

這裏是我的問題的jsfiddle:

https://jsfiddle.net/onedevteam/udmz34z0/6/

有人可以幫我解決這個問題?

+0

你可以分享可執行的演示/片段或[JSFiddle](https://jsfiddle.net/)嗎? – Rayon

回答

1

問題是,每當我加載圖像,reader.onload方法裏面的代碼執行兩次

這是因爲在你的代碼中有這樣的。

(reader.onload = function(file) { 
      //... 
      //... 
})(f = file.name); // <---- self executing function. 

reader.readAsDataURL(file); 

這裏使用的是「自我執行功能」爲reader.onload,所以會發生什麼是當它擊中這行代碼時reader.readAsDataURL(file)完成閱讀它會執行一次,一次。所以remove the "self executing function " and you logic will run only once

當我刪除(f = file.name),腳本執行,因爲它應該是,但然後我沒有file.name變量裏面的讀者範圍。

將文件名添加到變量中並像這樣使用它。

var fileName = file.name; 
reader.onload = function() { 
      //... 
      //... 
      output.name = fileName ; 
      output.id = fileName ; 
    }; // <-- self executing function REMOVED 

而且我覺得沒有必要保存,文件名變爲變量,因爲傳遞給函數變量file足以完成這項工作。以下是根據我的建議最終的代碼。

  function loadFile(file, callback) { 
      var reader = new FileReader(); 

      reader.onload = function() { 

       console.log(file.name); // 
       var output = document.createElement('input'); 
       output.type = 'image'; 
       output.classList.add('image-responsive'); 
       output.classList.add('col-xs-12'); 
       output.name = file.name; // 
       output.id = file.name; // 
       output.src = reader.result; 

       var x = document.getElementById('OrigName'); 
       x.appendChild(output); 

       return callback(output); 
      }; 

      reader.readAsDataURL(file); 
     } 
1

您打電話給reader.onload至少兩次。你在另一個函數loadFile()中有這個函數,你立即調用它(這就是爲什麼當你只有(f=file.name)時纔會看到這種行爲),但是在chooser.change函數中,你有那個調用loadFile()的for循環。也許你可以設置file.name變量,而不是(f=file.name),然後使reader.onload不自動執行。

1

你有你的代碼結構的方式,你的onload處理程序將被執行兩次,當你定義它時,然後當「load」事件觸發時再次執行。當你將函數定義包裝在parens中時:

(reader.onload = function (file) { ... })(f = filename) 

你在說「定義這個函數並立即執行它」。

你真正想要的是一個返回功能,這樣的功能:

function makeOnLoadHandler (filename) { 
    return function (file) { 
     // ... do whatever you need to with file and filename 
    }; 
} 

reader.onload = makeOnLoadHandler(someFileName); 

外功能,makeOnLoadHandler(),創建一個封閉在你的filename變量,而當內部函數處理讀者的load事件,它會看到您在調用makeOnLoadHandler時傳入的filename