r4v37t Posted January 13, 2011 Posted January 13, 2011 This ajax code: function getData(dataSource,id){ if (window.XMLHttpRequest){ // Mozilla, Safari httprequest=new XMLHttpRequest(); if (httprequest.overrideMimeType){ httprequest.overrideMimeType('text/xml'); } }else if (window.ActiveXObject){ // IE try { httprequest=new ActiveXObject("Msxml2.XMLHTTP"); }catch (e){ try{ httprequest=new ActiveXObject("Microsoft.XMLHTTP"); }catch (e){} } } if(httprequest){ var obj=document.getElementById(id); httprequest.open("GET",dataSource); httprequest.onreadystatechange=function(){ if(httprequest.readyState==4 && httprequest.status==200){ obj.innerHTML=httprequest.responseText; } } } httprequest.send(null); } function call_one(){ var link="http://localhost/first.php"; getData(link,'targetDIV_one'); } function call_two(){ var link="http://localhost/second.php"; getData(link,'targetDIV_two'); } in html code: <html> <head> </head> <body onload="call_one(); call_two();"> <div id="targetDIV_one"> </div> <div id="targetDIV_two"> </div> </body> </html> but the result in "targetDIV_one" and "targetDIV_two" just show result of function "call_two()", how this problems solve??? Quote
digip Posted January 13, 2011 Posted January 13, 2011 Both functions are calling the same var "link". Try making them unique. var link1=xxxx var link2=xxxxx. I haven't run or tested the code, but my guess is because they are the same, it is running both, but when it gets to function call_two() its going to replace what was called from function call_one() with what is in function call_two(). Quote
Jason Cooper Posted January 13, 2011 Posted January 13, 2011 Your problem is actually coming from a combination of two asynchronous call with just one httprequest object. Here is a quick walk through of what is happening. call_one uses the global httprequest object to request a GET method to retrieve some data. The http request will take a while so the code continues to run relying on the onreadystatechange event handler to call the function to handle the returned data. As your code is still running call_one finishes and call_two is then called. This uses the same httprequest object to make a different request using the GET method. The httprequest object forgets about its old request and just remembers the new request. Again as it is asynchronous your code continues to run relying on the eventhandler to call your function when the request completes. There is nothing else for your code to do after call_two, so the next thing that happens is the result from the first request comes back. Unfortunately the httprequest object has thrown away the details for that request so it ignores it. Then the result from the second request comes back and for some reason httprequest calls its onreadystatechange event handler twice with the result of the second call. The first event handler call uses the scope of call_one, so the obj variable points to targetDIV_one. The second event handler call uses the scope of call_two, so the obj variable points to targetDIV_two. I would recommend that you use JQuery rather than rolling your own ajax handlers. It makes your life easier and you can concentrate on your code rather than the code to speak to your the server. Also it makes it nice and easy to choose if you want to do an asynchronous call or not (in other words do you want your code to wait till you get response or do you want it to get on with other things while waiting). Also its asynchronous calls use a separate httprequest object for each call which avoids the problem you have encountered. Quote
r4v37t Posted January 13, 2011 Author Posted January 13, 2011 I would recommend that you use JQuery rather than rolling your own ajax handlers. It makes your life easier and you can concentrate on your code rather than the code to speak to your the server. Also it makes it nice and easy to choose if you want to do an asynchronous call or not (in other words do you want your code to wait till you get response or do you want it to get on with other things while waiting). Also its asynchronous calls use a separate httprequest object for each call which avoids the problem you have encountered. thanks for recommend but I want learn how ajax running :) Quote
Jason Cooper Posted January 13, 2011 Posted January 13, 2011 thanks for recommend but I want learn how ajax running :) In which case you will have to use multiple httprequest objects. You would keep yourself sane by writing a set of routines to handle your ajax calls. Quote
r4v37t Posted January 14, 2011 Author Posted January 14, 2011 Your problem is actually coming from a combination of two asynchronous call with just one httprequest object. Here is a quick walk through of what is happening. call_one uses the global httprequest object to request a GET method to retrieve some data. The http request will take a while so the code continues to run relying on the onreadystatechange event handler to call the function to handle the returned data. As your code is still running call_one finishes and call_two is then called. This uses the same httprequest object to make a different request using the GET method. The httprequest object forgets about its old request and just remembers the new request. Again as it is asynchronous your code continues to run relying on the eventhandler to call your function when the request completes. There is nothing else for your code to do after call_two, so the next thing that happens is the result from the first request comes back. Unfortunately the httprequest object has thrown away the details for that request so it ignores it. Then the result from the second request comes back and for some reason httprequest calls its onreadystatechange event handler twice with the result of the second call. The first event handler call uses the scope of call_one, so the obj variable points to targetDIV_one. The second event handler call uses the scope of call_two, so the obj variable points to targetDIV_two. thanks for that explain, i have ready solve this with adding code for check readyState this solve like this: function getData(dataSource,id){ if (window.XMLHttpRequest){ // Mozilla, Safari httprequest=new XMLHttpRequest(); if (httprequest.overrideMimeType){ httprequest.overrideMimeType('text/xml'); } }else if (window.ActiveXObject){ // IE try { httprequest=new ActiveXObject("Msxml2.XMLHTTP"); }catch (e){ try{ httprequest=new ActiveXObject("Microsoft.XMLHTTP"); }catch (e){} } } if(httprequest){ var obj=document.getElementById(id); httprequest.open("GET",dataSource); httprequest.onreadystatechange=function(){ if(httprequest.readyState==4 && httprequest.status==200){ obj.innerHTML=httprequest.responseText; } } } httprequest.send(null); } function call_one(){ var link="http://localhost/first.php"; if(httprequest.readyState==4||httprequest.readyState==0){ //check if httprequest in idle getData(link,'targetDIV_one'); }else{ setTimeout('call_one()',1000); //if httprequest busy retry again in 1 second } } function call_two(){ var link="http://localhost/second.php"; if(httprequest.readyState==4||httprequest.readyState==0){ //check if httprequest in idle getData(link,'targetDIV_two'); }else{ setTimeout('call_two()',1000); //if httprequest busy retry again in 1 second } } it's running well :) Quote
Jason Cooper Posted January 14, 2011 Posted January 14, 2011 You can avoid the need for checking state with a small change to your getData function. By adding a line at the start that makes httprequest local to the get data function then a fresh object is created with each call of the function. This object is available in your event handler thanks to the way that JavaScript scopes its variables. function getData(dataSource,id){ var httprequest=undefined; if (window.XMLHttpRequest){ // Mozilla, Safari httprequest=new XMLHttpRequest(); if (httprequest.overrideMimeType){ httprequest.overrideMimeType('text/xml'); } }else if (window.ActiveXObject){ // IE try { httprequest=new ActiveXObject("Msxml2.XMLHTTP"); }catch (e){ try{ httprequest=new ActiveXObject("Microsoft.XMLHTTP"); }catch (e){} } } if(httprequest){ var obj=document.getElementById(id); httprequest.open("GET",dataSource); httprequest.onreadystatechange=function(){ if(httprequest.readyState==4 && httprequest.status==200){ obj.innerHTML=httprequest.responseText; } } } httprequest.send(null); } } This can be a little tricky to get your head round when starting off, but the way it works is this. The first call creates a local httprequest object for that call of the getData function. Copies of these variables are available to your function that is defined within it, in this case the event handler. The second time the function is called a new httprequest object is created because when we declare httprequest we set it undefined. Setting httprequest to undefined doesn't destroy the object that it was pointing at as it is still pointed to by the first copy of the variable in the first instance of the event handler. So at this stage we have the old httprequest object existing to deal with the first call and a new one that we can use for the second call. We can repeated call this function and each call would use a new httprequest object and leave it available for it's event handlers. The down side to this method is that you do leave httprequest objects in memory (as garbage collection won't dump them as they are still in use by their own event handler). The benefit this method has over the one you are currently using is that the second call doesn't have to wait for the first httprequest to have completed before it can be sent. This will usually get you better performance from your AJAX code. There is a third alternative where you have a global array that stores your httprequest objects and when making a fresh request it loops through the array to find an available object (i.e. one with a readyState of 4 or 0). If it doesn't find one it creates a fresh one an puts pushes into the array. Either way it will have a usable httprequest that won't be reused until it has completed its request. This is a little more code but doesn't leave objects around that you will never be able to use again. Quote
r4v37t Posted January 15, 2011 Author Posted January 15, 2011 Thanks again Jason :) but one more question still about ajax, why when I get "responseText" from ajax from any file resource with contain javascript inside, why that javascript is not running well? example: function call_one(){ var link="http://localhost/first.php"; getData(link,'targetDIV_one'); } which inside 'first.php' : <script> alert("Hello World"); </script> <?php echo "Example of Ajax"; ?> why when 'call_one()' execute the result just show "Example of Ajax" without an alert from javascript? Quote
Jason Cooper Posted January 16, 2011 Posted January 16, 2011 This page has some interesting information on your script problem. I think that you should probably start looking at using XML for the values returned rather than just pushing HTML. That way you can have your javascript and html passed back as two seperate entries. You can then eval the javascript to run it and put the html into the div. If you do go down this road you will need to remember to encode your javascript and html to stop it causing problems when the XML is parsed. example of returned XML. (You will want to be using responseXML rather than responseText when you are using values returned in XML). <returns> <javascript>alert("Hello World");</javascript> <html>Example of AJAX</html> </returns> Quote
r4v37t Posted January 16, 2011 Author Posted January 16, 2011 its problems with this code: if (window.XMLHttpRequest){ // Mozilla, Safari httprequest=new XMLHttpRequest(); if (httprequest.overrideMimeType){ httprequest.overrideMimeType('text/xml'); } }else if (window.ActiveXObject){ // IE try { httprequest=new ActiveXObject("Msxml2.XMLHTTP"); }catch (e){ try{ httprequest=new ActiveXObject("Microsoft.XMLHTTP"); }catch (e){} } } that return MimeType to 'text/xml' maybe that cause every return as 'text/xml' in client-side except server-side code. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.