-1
var lines = [];
document.getElementById("fileInput").addEventListener("change", readSingleFile, true);

console.log(lines.length);


function readSingleFile(evt) {
    var f = evt.target.files[0];
    if (f) {
        var read = new FileReader();
        read.onload = function(evt) {
            var contents = evt.target.result;
            var ct = read.result;
            var lines = ct.split('\n');
        }
        read.readAsText(f);
    }
}


...
<body>
     <input type="file" id = "fileInput">
     <script src="index.js"></script>
</body>
...

I want to read the content of the file to array lines. The console.log(lines.length) returns 0(which I think is because variables in js have function scope). How can I access the values in array 'lines' outside of the function. Any help would be much appreciated!!

Majmun
  • 19
  • 5

2 Answers2

0

The issue is that your console.log() instruction runs immediately (before the change event of the fileInput or the load event of the FileReader). Move the console.log() into the load callback so that it runs when the file has been successfully loaded and lines is populated.

You do need to remove the var on the lines variable declaration inside your function though so that the original variable doesn't get shadowed.

var lines = [];
document.getElementById("fileInput").addEventListener("change", readSingleFile, true);

function readSingleFile(evt) {
    var f = evt.target.files[0];
    if (f) {
        var read = new FileReader();
        read.onload = function(evt) {
            var contents = evt.target.result;
            var ct = read.result;
            lines = ct.split('\n');

            console.log(lines.length);
        }
        read.readAsText(f);
    }
}
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
  • Thank you! But is it possible to access the array outside of the function? – Majmun Oct 29 '19 at 16:15
  • @Majmun By removing the second `var`, you won't have a second `lines` variable and, as long as you access `lines` after the events that populate it, you can access it from outside the function. – Scott Marcus Oct 29 '19 at 16:16
  • @Quentin Answer updated. – Scott Marcus Oct 29 '19 at 16:20
  • @Majmun — Time travel is not possible. You can't read a value before it is assigned. – Quentin Oct 29 '19 at 16:20
  • @Quentin but is it possible to put the 'console.log(lines.length)' anywhere outside of the function (doesn't matter where) and it will give me the number of the lines read? – Majmun Oct 29 '19 at 16:25
  • @Majmun – You could put it in a different function, which you don't call unless *after* you have assigned the value. But that would be silly. Pass arguments. Don't use globals. – Quentin Oct 29 '19 at 16:27
  • @Majmun As the whole point of my answer shows, you have to wait until `lines` is populated before you can access it, so no, you can't have `console.log()` anywhere outside the function. You can access `lines` from outside the function, but only after it's been populated. – Scott Marcus Oct 29 '19 at 16:32
0

you can create a custom event, and add a listener to it...

let lines = [];
const fileInput = document.getElementById("fileInput");

fileInput.addEventListener("change", readSingleFile, true)
fileInput.addEventListener('lines:filled', handleLines);

const event = new Event('lines:filled');

function readSingleFile(evt) {
    var f = evt.target.files[0];
    if (f) {
        var read = new FileReader();
        read.onload = function(evt) {
            var contents = evt.target.result;
            var ct = read.result;
            lines = ct.split('\n');
            
            fileInput.dispatchEvent(event);
        }
        read.readAsText(f);
    }
}

function handleLines() {
  console.log(lines);
}
<input id="fileInput" type="file"/>
Ivan Karaman
  • 1,224
  • 1
  • 7
  • 11