views:

87

answers:

4

I am having an issue with this variable not wanting to work outside the function and I just can't understand why! here's the code:

globalData = new Array();

 // 
 // Colors
 //
 if ( settings.category == 'colors' ) {
  $.getJSON(colorLoversURL, function(data) {
   for ( var i in data ) {
    var localData = data[i].hex;
    globalData.push(localData);
   }
  });
 }

 // 
 // Palettes
 //
 else if ( settings.category == 'palettes' ) {
  $.getJSON(colorLoversURL, function(data) {
   for ( var i in data ) {
    var localData = new Array();
    for ( var j in data[i].colors ) {
     localData.push(data[i].colors[j]);
    }
    globalData.push(localData);
   }
  });
 }

Now the thing is that globalData is only keeping the values inside the getJSON function and out of the function, when I need it, It just comes up blank (I test the values in an alert window). I also tried taking the 'var' on and off the front of the code. Is there something wrong here?

A: 

If it's on your .js file, then the very 1st line must be var globalData = new Array();

or if it's inside <script type="text/javascript">...</script> then your very next line will be

var globalData = new Array();

E.g.

<script type="text/javascript">
   var globalData = new Array();
   //Rest of JS code...
   function whatever() {

   }
</script>

then globalData becomes global.

The Elite Gentleman
+5  A: 

When are you inspecting globalData?

both calls to getJSON uses a callback to manipulate globalData so the function might not be called yet before you inspect globalData. Don't forget that you're using asynchronous javascript there.

If it is the case, I recommend using function chaining

 function useGlobalData() {
    alert(globalData); 
    //do other stuff
 }
 // 
 // Palettes
 //

  $.getJSON(colorLoversURL, function(data) {
   for ( var i in data ) {
    var localData = new Array();
    for ( var j in data[i].colors ) {
     localData.push(data[i].colors[j]);
    }
    globalData.push(localData);
    useGlobalData();
   }
  });
Charles Ma
How would asynchronous JS effect this? (it's easily turned off) I am inspecting global data in the very end.
Kyle
What's happening is that the function $.getJSON is returned almost instantly and doesn't call function(data) until the data becomes available. While it's waiting for data to arrive, your code may have reached the end where you print globalData
Charles Ma
Wow, I am pretty new to AJAX and am just learning this =) What I have ending the code is a return statement - so will the return statement wait for the async to finish, or would turning off async requests be the best option here?
Kyle
And what do you mean that it's easily turned off? I'm not aware of any way to turn it off other than restructuring your code using function chaining to make things synchronous...
Charles Ma
This isn't AJAX, it's just javascript :P Javascript's syntax may look very much like other procedure languages like C, but they're very different, javascript is event driven so code gets executed when an event occurs, in your case, when data becomes available. A return statement there probably won't work(most of the time, sometimes the data might return fast enough and it will work and confuse the heck out of you :P)What you should do is as I suggested, use function chaining to call the code after you need globalData. do a quick google search for function chaining or see my exampl:)
Charles Ma
Charles has it right... I was about to post basically the same code. It is a timing issue because of the callbacks. If a call is async (as your Ajax call to getJson is) then code after it continues execution. It doesn't wait for the callback before it proceeds. A return statement after the code will return immediately.
Lindsay
Is there a way to use function chaining to do the main (parent) functions `return`? I know it sounds far fetched but I am trying to get the the JSON data downloaded to be pushed in the main `return` function in the end.
Kyle
@Kyle: no. You can't make asynchronous code synchronous or vice versa (without language features like threads or continuations, which JavaScript doesn't have). Incidentally, don't use `for...in` against a sequence such as an `Array`. It doesn't do what you think and is likely to give you weird errors. `for...in` is for enumerating the keys of an `Object` mapping; for sequences use a variant of the standard C-style `for (var i= 0; i<seq.length; i++)` loop.
bobince
A: 

This should work. Is it possible that the code runs twice somehow, causing globalData to be reset back to an empty array?

levik
A: 

Hi Kyle,

You are operating inside a javascript closure, and inside a closure you have a distinct scope.

What this means is that only stuff defined within the scope will be accessible to you.

simply saying x = something() does not create a global ( a variable that will be accessible from all scopes ).

TO do that you need to do var x = something();

rmk
Declaring a variable without using the var statement makes it global, unless it has already defined in the current scope; in which case it will override that value.
Matt