tags:

views:

88

answers:

2

Not sure if the problem is related to Ajax or something silly about JavaScript that I'm overlooking in general, but I have the following script where fox.html is just plain text that reads, "The quick brown fox jumped over the lazy dog." :

function loadXMLDoc()
{
if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
  xmlhttp=new XMLHttpRequest();
  }
else
  {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }

xmlhttp.open("GET","fox.html",true);
xmlhttp.send();

xmlhttp.onreadystatechange=function()
  {
  if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
    fox = xmlhttp.responseText;
    alert(fox);
    }
  }

}

onload = loadXMLDoc;

The above script alerts the contents of fox.html onload just fine. However if I change the script so that:

{
fox = xmlhttp.responseText;
alert(fox);
}

becomes:

{
fox = xmlhttp.responseText;
return fox;
}

and alert(loadXMLDoc()); onload I get 'undefined'.

I'm wondering why this is so.

+1  A: 

Because the return is in the scope of the xmlhttp.onreadystatechange function and not your loadXML function. This is how asynchronous requests work, they run in the background while the code already continues. When the request is finished it calls a function, which is usually set on the onreadystatechange.

So quick example; in FunctionA you start the XMLHTTP request, which on completion calls the onreadystatechange function that calls FunctionB with the responseText.

If you want to have the code wait for a response, you need to use a synchronous request - however, doing so stalls the entire browser until the request finishes. So it's best to just adjust your code to what I wrote in the first paragraph.

CharlesLeaf
Thanks for the explanation. Not sure what you mean by adjusting my code to what you wrote in the first paragraph however. What did you write in the first paragraph?
George
He means to change the function you create and attach to the `onreadystatechange` event listener to process the returned XML and not return it.
Matt S
@Matt Ah got it. So like in my original example where I'm alerting the response instead of returning it (except obviously doing more than just alert). Thanks.
George
+1  A: 

AJAX is asyncronous. Therefor your call to alert(loadXMLDoc()) isn't actually returning anything.

xmlhttp.onreadystatechange=function()
  {
  ...
  }

This creates a new function and attaches it to the xmlHTTP object. When the state changes (the event is fired) this function is executed. It is NOT executed during the run of loadXMLDoc() but instead at some point in the future. This is done to maintain usability in your web application (things aren't waiting for something to complete).

The data that gets returned from your AJAX request has to be acted upon in this new function you've created. You should update the necessary pieces of your page w/ the returned information. It cannot return any data, well actually it can return all it wants but nothing will be done with that information.

You can also define a new function somewhere else and attach it to the onreadystatechange event handler by doing:

fucntion handler() { ... }

xhmlhttp.onreadystatechange = handler;
Matt S
Hmm I'm not sure I follow completely. So you're saying loadXMLDoc() completes before the onreadystatechange function executes because it's set to fire once the client receives a response from the browser? But then how do I target onreadystatechange function to return the value... or is that impossible in this case and I can only have the value update something on the page like a div?
George
Your latter statement is correct, the handler function needs to process the returned data. It's all on its own so to speak when it comes to scope. It has the data it received from the XML request and everything that's global to your page but that's it. And yes, `loadXMLDoc()` will return before the ajax has completed. `..statechange = handler` is no different than `var a = 5` as far as JS is concerned so there's no actual processing happening.
Matt S
Thanks for the clarification!
George