I have the following HTML Code:
<input type='file' multiple>
And Here's my JS Code:
var inputFiles = document.getElementsByTagName("input")[0]; inputFiles.onchange = function(){ var fr = new FileReader(); for(var i = 0; i < inputFiles.files.length; i++){ fr.onload = function(){ console.log(i) // Prints "0, 3, 2, 1" in case of 4 chosen files } } fr.readAsDataURL(inputFiles.files[i]); }
So my question is, how can I make this loop synchronous ? That is first wait for the file to finish loading then move on to the next file. Someone told me to use JS Promises. But I can't make it to work. Here's what I'm trying:
var inputFiles = document.getElementsByTagName("input")[0]; inputFiles.onchange = function(){ for(var i = 0; i < inputFiles.files.length; i++){ var fr = new FileReader(); var test = new Promise(function(resolve, reject){ console.log(i) // Prints 0, 1, 2, 3 just as expected resolve(fr.readAsDataURL(inputFiles.files[i])); }); test.then(function(){ fr.onload = function(){ console.log(i); // Prints only 3 } }); }; }
Thanks in advance...
The FileReader object lets web applications asynchronously read the contents of files (or raw data buffers) stored on the user's computer, using File or Blob objects to specify the file or data to read.
The FileReader methods work asynchronously but don't return a Promise. And attempting to retrieve the result immediately after calling a method will not work, as the . onload event handler fires only after the FileReader has successfully finished reading the file and updates the FileReader's .
You can use the standard FileReaderSync, which is a simpler, synchronous, blocking version of the FileReader API, similar to what you are already using: let reader = new FileReaderSync(); let result_base64 = reader. readAsDataURL(file); console. log(result_base64); // aGV5IHRoZXJl...
We modified midos answer to get it to work the following:
function readFile(file){ return new Promise((resolve, reject) => { var fr = new FileReader(); fr.onload = () => { resolve(fr.result ) }; fr.onerror = reject; fr.readAsText(file.blob); }); }
If you want to do it sequentially( not synchronously) using Promises, you could do something like:
var inputFiles = document.getElementsByTagName("input")[0]; inputFiles.onchange = function(){ var promise = Promise.resolve(); inputFiles.files.map( file => promise.then(()=> pFileReader(file))); promise.then(() => console.log('all done...')); } function pFileReader(file){ return new Promise((resolve, reject) => { var fr = new FileReader(); fr.onload = resolve; // CHANGE to whatever function you want which would eventually call resolve fr.onerror = reject; fr.readAsDataURL(file); }); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With