|
One of the things that pops out at most developers is the thread safety issues of the example code. While the example works fine for testing, the very nature of programming web apps in this manner means it is *extremely* likely multiple requests will be issued concurrently.
The following is thread-safe code to do just that. I've used the Ajax moniker, as that is what a lot of people call this technique. Personally, I don't care if they call it furrycatofdeath, as long as it works. :)
Essentially, this code uses a technique called inner functions. These are useful in this situation because the variables declared on the outer function are available to the inner function -- and do not fall out of scope until *after* the inner function has been executed. Since the request and callback variables (which contain function pointers to the good stuff) are declared locally, each call to the ajaxSend function creates a new copy, so the previous one is left intact.
A great discussion and analysis of this methodology (and other similar methodologies) is described in detail at
http://jibbering.com/faq/faq_notes/closures.html
Mind you, I found this via a Google search and I am completely unrelated with its content, so that url may change without my knowledge. Hopefully it will not, as it is a very clear and well written article!
At any rate, the source follows. If you have issues with it, please let me know, as I haven't had a chance to test many platforms yet. Thank you!
// threadsafe asynchronous XMLHTTPRequest code
function ajaxSend(url, callback){
// we use a javascript feature here called "inner functions"
// using these means the local variables retain their values after the outer function
// has returned. this is useful for thread safety, so
// reassigning the onreadystatechange function doesn't stomp over earlier requests.
function ajaxBindCallback(){
if (ajaxRequest.readyState == 4) {
if (ajaxRequest.status == 200) {
if (ajaxCallback){
ajaxCallback(ajaxRequest.responseXML);
} else {
alert('no callback defined');
}
} else {
alert("There was a problem retrieving the xml data:\n" + ajaxRequest.status + ":\t" + ajaxRequest.statusText + "\n" + ajaxRequest.responseText);
}
}
}
// use a local variable to hold our request and callback until the inner function is called...
var ajaxRequest = null;
var ajaxCallback = callback;
// bind our callback then hit the server...
if (window.XMLHttpRequest) {
// moz et al
ajaxRequest = new XMLHttpRequest();
ajaxRequest.onreadystatechange = ajaxBindCallback;
ajaxRequest.open("GET", url, true);
ajaxRequest.send(null);
} else if (window.ActiveXObject) {
// ie
ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP");
if (ajaxRequest) {
ajaxRequest.onreadystatechange = ajaxBindCallback;
ajaxRequest.open("GET", url, true);
ajaxRequest.send();
}
}
}
|