0

I'm sorry if this is a duplicate, but I've read a few posts about variable scope and I can't seem to figure this out. Any help is much appreciated.

Basically, I'm just trying to read in a csv and determine how many rows it has and then assign number to a global variable. Here is my code:

<script src="https://d3js.org/d3.v4.min.js" charset="utf-8"></script>
<script type="application/javascript">  
    var maxEpochs;

    setMaxEpochs();
    console.log(maxEpochs);

    function setMaxEpochs() {
        /*
        for (i = 0; i < 2; i++) {
            if ( document.chooseModel.model[i].checked ) {
                modelChoice = document.chooseModel.model[i].value;
                break;
            }
        }
        console.log(modelChoice);
        */


        // set initial value for maxEpochs I DON'T UNDERSTAND WHY THIS DOESN'T WORK
        d3.csv("epochStats.csv", function(d) {
            console.log(d.length);
            maxEpochs = d.length;
            console.log(maxEpochs);
        });
        console.log(maxEpochs);

    }

</script>

NOTE: epochStats.csv just has to be a csv with a few lines in it. That data doesn't matter for this example.

So, when I run this I get the following output in my console:

maxEpochsFail.html:31 undefined
maxEpochsFail.html:12 undefined
maxEpochsFail.html:27 101
maxEpochsFail.html:29 101

The line numbers might not quite match (I have some <head> tags etc at the top), but the point is, the first two console.logs within the function print 100 which is the correct number, but then once I'm outside the function it reverts to undefined.

Any thoughts on this would be much appreciated. I'm kind of banging my head against the wall with it. Thanks, Seth

1
  • I won't close this question (yes, it is a duplicate!) because I feel sorry for your head being banged against the wall! Here is a good reading for you: stackoverflow.com/questions/6847697/… . Please read Felix Kling answer to the end, it's worth it. Commented Mar 7, 2017 at 12:30

1 Answer 1

1

This is due to the asynchronous nature of javascript. The blocks of code you write do not get evaluated "in order" as you might expect. Basically, anything that uses the d3.csv call HAS to be within that block:

d3.csv("epochStats.csv", function(d) {
        console.log(d.length);
        maxEpochs = d.length;
        console.log(maxEpochs);
        // anything else that uses the value of maxEpochs, or reads the file data, etc....
});
console.log(maxEpochs);  <-- This could be evaluated before the above csv block.
Sign up to request clarification or add additional context in comments.

3 Comments

I see. So, what is the best way to handle this if I need to have that function run before the other functions (because I need to set maxEpochs and I have to load a csv file to set it)? Right now I am just have onload="setMaxEpochs(); anotherFunction(maxEpochs);" in the body tag of the page, but I guess that isn't working.
One option would be to have everything within the d3.csv function call, that seems to be quite common with d3.
Ok, I figured out a solution: If a call onload="setMaxEpochs(); setTimeout(anotherFunction(maxEpochs),200);" instead, then the 200 ms that it waits before trying the other function are enough time for it to set the maxEpochs variable. Someone can let me know if this is a bad idea for any reason, but it seems to work. Thanks to @tim-b for pointing out the asynchronousity being the issue!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.