views:

38

answers:

2

I am refactoring some code. I have a PHP page that contains a MySQL query and stores the result in a PHP variable $my_result. This result is then echoed to a Flash SWF during embedding with SWFObject.

I now want to call this PHP page that makes the query from a javascript function like so - one change I have made to the PHP is that instead of storing the result in a variable $my_result I am echoing the result.

Javascript function to call the PHP page and make the database query

function getNewUploads() {
if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
       xmlhttp=new XMLHttpRequest();
    }
    else {// code for IE6, IE5
       xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
    }
    xmlhttp.onreadystatechange=function() {
       if (xmlhttp.readyState==4 && xmlhttp.status==200) {
    alert(xmlhttp.responseText); // shows the correct output in an alert box
    return xmlhttp.responseText;
       }
    }
 xmlhttp.open("GET","dBaseConnect_uploadStep2.php",true);
 xmlhttp.send();    
}

Then I have the embedding of the Flash which I only want to happen when a certain tab is clicked on a page and is handled by jabvascript -

function show_tab(tab_id) {

    $(tab_id).show();
    if(tab_id == "#tab_2") {
      var data_string = getNewUploads(); // CALLING THE FUNCTION TO CALL THE PHP QUERY  
      alert(data_string); // shows undefined in the alert box
      var so = new SWFObject(".....");          
      so.addVariable("theDataString", data_string); 
      so.write("flashcontent2");
    }
}

So it seems that the getNewUploads() function does not return the result from the PHP page.

Can anyone shed some light on my mistake please. Thanks

+3  A: 

The call is asynchronous. After you call send, the call begins in the background. In the meantime, getNewUploads returns. Later, the function you've assigned is called with the answer. When you do return xmlhttp.responseText, you're returning from this anonymous function (assigned to onreadystatechange), not from getNewUploads (which is already done).

You can use a callback instead. Something like:

function getNewUploads(callback) {
    if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
       xmlhttp=new XMLHttpRequest();
    }
    else {// code for IE6, IE5
       xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
    }
    xmlhttp.onreadystatechange=function() {
       if (xmlhttp.readyState==4 && xmlhttp.status==200) {
         callback(xmlhttp.responseText);
       }
    }
    xmlhttp.open("GET","dBaseConnect_uploadStep2.php",true);
    xmlhttp.send();    
}

function show_tab(tab_id) {
    $(tab_id).show();
    if(tab_id == "#tab_2") {
      getNewUploads(function(data_string) {
        alert(data_string);
        var so = new SWFObject(".....");          
        so.addVariable("theDataString", data_string); 
        so.write("flashcontent2");
      }); // CALLING THE FUNCTION TO CALL THE PHP QUERY  
    }
}

We define getNewUploads to take a single argument, callback. Then, in the success function, we call the callback with a single argument, the response text. In show_tab, we pass an anonymous function that takes a single parameter (the response text) to getNewUploads, as the callback parameter.

Matthew Flaschen
Remove the comment `// shows undefined in the alert box` - that can be misleading.
Amarghosh
Brilliant - that is exactly what was needed - works perfectly. Many thanks.
undefined
A: 

The true in xmlhttp.open("GET","dBaseConnect_uploadStep2.php", true); makes it asynchronous and hence the error. Change it to:

function getNewUploads() {
  //initialize xmlhttp
  xmlhttp.open("GET", "dBaseConnect_uploadStep2.php", false);
  xmlhttp.send();    
  if(xmlhttp.status == 200) 
    return xmlhttp.responseText;
  else
    return "Oops :(";
}
Amarghosh
You loose the whole advantage of Ajax if you use synchronous calls imho.
Felix Kling
@Felix agreed. I was just showing the `async` property... callback is the correct way to go
Amarghosh