Wednesday, August 09, 2006

Making simultaneous AJAX requests

During creation of Sametime Web Contact I had to create functionality which process simultaneously 2 web requests: the first request is continiously looping and fetching updates from server-side and the second request is triggered on-demand upon user's actions (send message, change status) and is executed only once. Both are done in asynchronous mode in order to not block the web browser.
Here is an example of how I implemented it:


<script>
var scriptpath="test2.html";
var default_parameters="par1=aaa&par2=bb&par3=ccc";
var stopLooping=false;

function initHTTP(){
var http_request = false;
if (window.XMLHttpRequest) { // Mozilla
http_request = new XMLHttpRequest();
}
else if (window.ActiveXObject) { // IE
try {
http_request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
http_request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
if (!http_request) {
alert('Your web browser is not compatible');
return false;
}

return http_request;
}


function makeAsyncRequestLoop(parameters) {
if(stopLooping==false){
if (parameters=="") parameters=default_parameters;
var http_request1=initHTTP();
http_request1.onreadystatechange = function() { readyhandler(http_request1, true); };
http_request1.open('POST', scriptpath, true);
http_request1.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http_request1.setRequestHeader("Content-length", parameters.length);
http_request1.setRequestHeader("Connection", "Keep-Alive");
http_request1.send(parameters);
}

}
function makeAsyncRequestOnce(parameters){
var http_request2=initHTTP();
http_request2.onreadystatechange = function() { readyhandler(http_request2, false); };
http_request2.open('POST', scriptpath, true);
http_request2.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http_request2.setRequestHeader("Content-length", parameters.length);
http_request2.setRequestHeader("Connection", "Keep-Alive");
http_request2.send(parameters);
}

function readyhandler(http_requestobj, fetchloop) {
if (http_requestobj.readyState == 4){
if (http_requestobj.status == 200) {
document.getElementById("test").innerHTML=(new Date().getTime())+" "+http_requestobj.responseText;
if(fetchloop==false) alert((new Date().getTime())+" "+http_requestobj.responseText)
}
if(fetchloop==true) {
makeAsyncRequestLoop(default_parameters); //request same web page again
}
}
}

function startLoop(){
stopLooping=false;
makeAsyncRequestLoop(default_parameters);
}
function stopLoop(){
stopLooping=true;
}
function customRequest(param){
makeAsyncRequestOnce(param);
}
</script>

<input type="Button" name="Start" value="Start" onClick="startLoop()">
<input type="Button" name="Stop" value="Stop" onClick="stopLoop()"><br><br>
<input type="Button" name="Custom" value="Custom" onClick="customRequest('p1=abc&p2=cde')">
<br><br><br>
<div id="test"></div>


If you test the code, you will see that the fetch loop continues getting new data even when the alert box is being shown.

Warning: IE and Firefox can handle only 2 concurrent connections to the same server. The third connection will get queued until one of the previous connections are released. So if you send 2 requests which take 2 minutes to accomplish, the third request will be queued for 2 minutes until processed. This little "feature" took me 2 days to realize.


Technorati:

1 comment:

Anonymous said...

Hi Andrei,

I used your simultanous AJAX request and altered it a little bit, but i have a problem. I have made an ongoing request like you did, but IE seems to only keep the connection open for around 13 seconds and Firefox for around 1 min 38 seconds!

This is very strange, but you will see what I mean if you go to http://www.nmcmahon.co.uk/ajax/chatv2/.

Do you have any idea why?

Regards,

Niall