FileReader onload с результатом и параметром

Я не могу получить как результат 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. Если я использую параметр, например файл, для этой функции, я больше не могу получить доступ к результату. Например, я хотел бы использовать file.name в функции onload. Как решить эту проблему?

Ответы

Ответ 1

Попробуйте обернуть функцию 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

Вы должны использовать закрытие в обработчике 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);

Ответ 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);
});

Ответ 4

Для машинописных;

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

  var reader = new FileReader();

  reader.onload = ((file: any) => {
    return (e: Event) => {
      //use "e" or "file"
    }
  })(file);

  reader.readAsText(file);
}

Ответ 5

Поскольку переменный файл находится в пределах области действия, вы можете использовать переменную файла, не передавая ее функции.

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/>