2

I can't figure out why specialArray is not keeping its values outside of $.getJSON. I thought I understood scope, any help appreciated. It spits out values to the console, but loses the values once it gets outside .getJSON. Any ideas?

var specialArray = [];
var data, temp, regionArrayNumber;
var numberOfRegions = 29;
var chartData = [];
$(document).ready(function() {

  // set up array of objects, organized by region_id
  for (var j = 0; j < numberOfRegions; j++) {
    temp = {
     "region_id" : (j + 1),
     "number_of_reads" : 0,
     "bus_count" : 0,
     "reads_per_bus" : 0
    };
    chartData.push(temp);
  }

  $.getJSON('https://data.cityofchicago.org/resource/historical-traffic-congestion-region.json', function(data) {

    // cycle through objects, add numbers to totals
    for (var i = 0; i < data.length; i++) {
      regionArrayNumber = data[i].region_id - 1;  // get region id, offset because of zero-based array
      chartData[regionArrayNumber].bus_count += parseInt(data[i].bus_count);
      chartData[regionArrayNumber].number_of_reads += parseInt(data[i].number_of_reads);
    }

    // calculate avg reads per bus
    for (var k = 0; k < chartData.length; k++) {
      chartData[k].reads_per_bus = (parseInt(data[k].number_of_reads)) / (parseInt(data[k].bus_count));
    }

    // set up array for google chart
    for (var x = 0; x < chartData.length; x++) {
      var tempArray = [];
      tempArray[0] = chartData[x].region_id;
      tempArray[1] = parseInt(chartData[x].number_of_reads);
      specialArray.push(tempArray);
      console.log("Inside: " + specialArray[x][0] + ", " + specialArray[x][1]);
    }
  });
console.log("Outside: " + specialArray[1][0]);


});  // end of doc.ready
sdfair
  • 39
  • 3

1 Answers1

1

The good news is that you understand scope just fine :)

getJSON is an asynchronous function... that means it will kick off the service call, move on with the next statement (which is console.log("Outside: " + specialArray[1][0]);) and then when the service call completes it will get around to invoking your callback function (what you called 'inside').

If you want to act on the result of the service call, that code needs to either live inside the callback function or be invoked by something inside the callback function.

The reason getJSON and similar APIs are like this is because they want to make sure your code doesn't 'hang' and make the browser unresponsive while waiting for something that could take a while to complete. Kinda tricky to wrap your head around at first but it's doing you a favor.

Robert Levy
  • 28,747
  • 6
  • 62
  • 94
  • So that explains why the Outside: was logging before Inside... How can I fix this so I can use specialArray later? – sdfair Jul 26 '14 at 01:15
  • the data is available, it just depends on how you define 'later' :) if you have an event handler for a button being clicked for example, in that handler you can check specialArray.length===0 to see if the data has been retrieved yet and then act accordingly. if you dont want the user clicking the button until the data is retrieved, disable the button at first and then re-enable it inside your getJSON callback. – Robert Levy Jul 26 '14 at 01:18