Javascript, ajax, and class-oriented programming
Matthew Martin
2/25/2015 01:05:00 PM
Tweetable
function getHTTPObject() {
var xhr;
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
} else if (window.ActiveXObject) {
xhr = new ActiveXObject("Msxml2.XMLHTTP");
}
return xhr;
}
function ajaxCall(dataUrl,dataStorageObject) {
var request = getHTTPObject();
request.onreadystatechange = function () {
if (request.readyState === 4 && request.status === 200) {
var jsonResponse = JSON.parse(request.responseText);
dataStorageObject=jsonResponse;
}
}
request.open("GET", dataUrl, true);
request.send(null);
}
var xhr;
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
} else if (window.ActiveXObject) {
xhr = new ActiveXObject("Msxml2.XMLHTTP");
}
return xhr;
}
function ajaxCall(dataUrl,dataStorageObject) {
var request = getHTTPObject();
request.onreadystatechange = function () {
if (request.readyState === 4 && request.status === 200) {
var jsonResponse = JSON.parse(request.responseText);
dataStorageObject=jsonResponse;
}
}
request.open("GET", dataUrl, true);
request.send(null);
}
There are a number of reasons we might want to use a class-oriented approach along with ajax in javascript--in webpage with lots of user inputs, for example, classes help to encapsulate, protect, and manage those inputs in a safe, conflict-free way (ie, where user inputs define the internal state of an object at the time it is created, this allows the inputs to change while the object based on the original inputs can still be used). Now suppose we have a data class object like this
function Class1(){
var internalData=[];
this.UpdateData=function(){
ajaxCall('http://mydomain.com/handler1.ashx?param=value',internalData);
}
this.DisplayData=function(){
return internalData;
}
}
var internalData=[];
this.UpdateData=function(){
ajaxCall('http://mydomain.com/handler1.ashx?param=value',internalData);
}
this.DisplayData=function(){
return internalData;
}
}
All of that works fine, I guess, although I'd rather not have to expose internalData to the ajaxCall function. This is necessary because the data returned by our GET request exists only inside the scope of the request.onreadystatechange method in ajaxCall. We need to get the data out of there somehow. We can't just use a return statement because the call is asynchronous--javascript executes the ajaxCall function synchronously, but loads the data asynchronously, meaning that the data won't exist yet when we try to return it. Instead, we simply expose the object where we want ajaxCall to eventually store the data.
But this creates problems, because it means essentially that our code is not thread-safe. For example, suppose we do this:
var myClass1=new Class1();
myClass1.UpdateData();
var myVar=myClass1.DisplayData();
myClass1.UpdateData();
var myVar=myClass1.DisplayData();
My question is, what is the best way to handle this? Usually it is possible to write the code in such a way that whatever you want to do with the data is done from inside the ajaxCall function, but I want a different way, one that doesn't corrupt the class-oriented pattern. It is easy enough to check whether the data has arrived yet, but that isn't really good enough. We really need the program to wait until the data is loaded before executing, ideally without blocking other parts of the program that don't need this data from running. Should we use a timer and keep checking periodically till the data is there? That sounds like a terribly inefficient solution. Make the ajaxCall synchronous?