smallfishinthesea
smallfishinthesea

Reputation: 3

Set a JSON object in a Javascript function and pass it to another function

I'm trying to set a JSON object from a Javascript function and use it as parameter in another function, but this obj has no value outside the function. I created this json object outside the function:

var obj = {"Level":0, "Index":0, "Count":0, "AABB":[], "Point":[], "Children":[]};

Then

function loadXMLDoc()
  {  
   if(window.XMLHttpRequest){
      xmlhttp=new XMLHttpRequest();
   } else {
      xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
   }
   xmlhttp.onreadystatechange=function(){
      if(xmlhttp.readyState==4 && xmlhttp.status==200){
        var string = xmlhttp.responseText;
        obj = JSON.parse(string);
        document.getElementById("myDiv").innerHTML = obj.Children;
      }
   }
   xmlhttp.open("GET","r0.json",true);
   xmlhttp.send();

   return obj;  
  }

but after I call the function and pass the obj, like this:

    var obj = loadXMLDoc();
    initGL(canvas);
    initShaders();
    initBuffers(obj);

It cannot pass the value to function initBuffers. Why did that happen and how can I solve that? Thanks.

Upvotes: 0

Views: 937

Answers (4)

MDDY
MDDY

Reputation: 225

Variables inside functions are bound to that particular function and can not be reached from outside the function unless they are within the function containing the variable or if the variable is set to be global.

If its only a few objects a dirty way is to create a span that you use a global container.

Upvotes: 0

like @akonsu said's the return of your loadXMLDoc function is called before the ajax call finish because that call is asynchronous so when you do an ajax there is created another process with that call, then the current process (with the function loadXMLDoc) works unconcerned, only the code inside the onreadystatechange function is called when the call ends, so i suggest to you to create a function callback that executes the code inside the ajax onreadystatechange like this:

function loadXMLDoc()
  {  
   if(window.XMLHttpRequest){
      xmlhttp=new XMLHttpRequest();
   } else {
      xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
   }
   xmlhttp.onreadystatechange=function(){
      if(xmlhttp.readyState==4 && xmlhttp.status==200){
        var string = xmlhttp.responseText;
        var obj = JSON.parse(string);
        document.getElementById("myDiv").innerHTML = obj.Children;
        SOME_CALLBACK(obj)  
      }
   }
   xmlhttp.open("GET","r0.json",true);
   xmlhttp.send();

   //return obj;  no needed any more
  }

function SOME_CALLBACK(obj){
    initGL(canvas);
    initShaders();
    initBuffers(obj);
}

So this way the SAVE_CALLBACK function receives the asynchronous obj data and works with these.

Upvotes: 0

Terry
Terry

Reputation: 14219

Because of what @akonsu said (synchronous nature of onreadystatechange), loadXMLDoc() will still be running when your init functions are run. As a result your obj variable will not yet be defined when initBuffers(obj) is run.

A simple solution is to add a callback to loadXMLDoc():

function loadXMLDoc(objParsed)
  {  
   ...
   xmlhttp.onreadystatechange=function(){
      if(xmlhttp.readyState==4 && xmlhttp.status==200){
        var string = xmlhttp.responseText;
        obj = JSON.parse(string);
        document.getElementById("myDiv").innerHTML = obj.Children;
        objParsed(obj);
      }
   }
   xmlhttp.open("GET","r0.json",true);
   xmlhttp.send(); 
  }

and use it like this (assuming initGL() and initShaders() don't rely on the result of initBuffers()):

loadXMLDoc(initBuffers);
initGL(canvas);
initShaders();

And as an aside, you appear to be changing the value of obj:

obj = JSON.parse(string);

So when you later try and access obj.Children it won't exist unless your xmlhttp.responseText is valid JSON and has a Children property off the root. It will also completely overwrite the value you set at the top of your script.

Upvotes: 0

akonsu
akonsu

Reputation: 29538

I am not sure what you mean when you say that you cannot pass obj as a parameter, but one thing to realize is that your onreadystatechange handler is called asynchronously, after you call initBuffers. Perhaps, you need to call your initialization routines from inside the handler, when the JSON response is parsed.

Upvotes: 2

Related Questions