2016-06-17 4 views
0

По какой-то причине, когда элементы передаются в массив в функции события FileReader.onload, элементы этого массива позже недоступны. Рассмотрим следующий код:Почему не удается получить доступ к элементам массива? (javascript)

scope.targets = []; 

for(var i = 0; i < files.length; i++){ 
     var reader = new FileReader(); 
     reader.readAsDataURL(files[i]); 

     reader.onload = function(e){ 
       scope.targets.push(e.target.result); 
     }; 
} 

console.log(scope.targets); 
console.log(scope.targets[0]); 

Это результат выходов console.log() в браузере Google Chrome. Как вы видите, scope.targets показывает, что существует элемент типа string. Однако scope.targets [0] не определен. Почему это происходит? Есть ли другой способ доступа к элементу?

enter image description here


************************** UPDATE *********** **************************


Вот решение. Спасибо вам, Ashwin Balamohan и nnnnn за ваши ответы, это заставило меня найти решение. Я нашел то, что искал здесь How to implement Progress Bar and Callbacks with async nature of the FileReader

Решение является:

scope.targets = []; 

for(var i = 0; i < files.length; i++){ 
     var reader = new FileReader(); 
     reader.readAsDataURL(files[i]); 

     reader.onload = function(e){ 
       scope.targets.push(e.target.result); 
       if(i == files.length){ 
        callback(); 
       } 
     }; 
} 

var callback = function(){ 
    console.log("scope.targets:"); 
    console.log(scope.targets); 
    console.log("scope.targets[0]:"); 
    console.log(scope.targets[0]); 
} 
+0

в связи с характером вашего запроса, мы не можем воспроизвести это без труда. вам было бы лучше сделать jsFiddle или что-то, что мы можем использовать, чтобы увидеть проблему. –

+1

Массив заполняется внутри функции, которая запускается асинхронно, а операторы 'console.log()' выполняются до того, как это произойдет. В зависимости от используемого браузера консоль может хранить ссылку на объект, который регистрируется таким образом, что к тому времени, когда вы развернете массив в консоли, в нем есть значения, даже если он был пуст при регистрации. Попробуйте сказать 'console.log (JSON.stringify (scope.targets))' в той же точке и посмотреть, что произойдет. – nnnnnn

ответ

0

Вы можете попробовать это один

scope.targets = {}; 

for(var i = 0; i < files.length; i++){ 
     var reader = new FileReader(); 
     reader.readAsDataURL(files[i]); 

     reader.onload = function(e){ 
       scope.targets[i] = (e.target.result); 
     }; 
} 

console.log(scope.targets); 
console.log(scope.targets[0]); 
+0

Почему это имеет значение? – nnnnnn

0

Код выполняющийся асинхронно. Смотрите комментарии ниже

scope.targets = []; 

for(var i = 0; i < files.length; i++){ 
     var reader = new FileReader(); 
     reader.readAsDataURL(files[i]); 

     // below is an asynchronous call 
     reader.onload = function(e){ 
       scope.targets.push(e.target.result); 
     }; 
} 

// the asynchronous calls above may or may not be complete by the time you get here 
console.log(scope.targets); 
console.log(scope.targets[0]); 

Что вы можете сделать, это изменить вашу reader.onload функцию, чтобы она выполняет console.log в функции обратного вызова:

scope.targets = []; 

for(var i = 0; i < files.length; i++){ 
     var reader = new FileReader(); 
     reader.readAsDataURL(files[i]); 

     // below is an asynchronous call 
     reader.onload = function(e){ 
       scope.targets.push(e.target.result); 
       // log out the array here, instead 
       console.log(scope.targets); 
     }; 
} 
+0

Да, установка console.log (scope.targets) в функции reader.onload работает. Однако мне нужны данные scope.targets массива вне функции reader.onload. –

+0

Ваш ответ верный. Однако я надеялся на решение. –

+0

Отлично, @Ellioticus. Я рад, что смог помочь в конце. –

Смежные вопросы