Javascript, ajax, and class-oriented programming

2/25/2015 01:05:00 PM
Tweetable
I'm curious what the best approach is to implement an asynchronous ajax request in a class-oriented way (more commonly known as "object-oriented programming" but "class-oriented" is a more appropriate term). A javascript ajax function looks like this:
    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);
    }
I know it's popular to do this in jquery, but jquery is just doing this, with 50kb worth of extra crap (side note: the getHTTPObject function isn't even necessary going forward, now that Microsoft is finally on board with XMLHttpRequest objects). I don't want to hear anything about jquery unless it specifically solves the question.

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;
    }
}
This class has a private property internalData that cannot be accessed from outside the object, and two public methods, UpdateData and DisplayData, that can be invoked from outside the object. The array internalData just stores the data, which because it cannot be accessed from outside, protects it from accidental misuse. UpdateData makes a GET http request to our server, and saves it to internalData, which we exposed to it in the function call.

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();
Most likely, myVar will be empty when you try to use that data. The reason is that ajaxCall is still waiting for data to arrive from the server when javascript moves on to try to execute var myVar=myClass1.DisplayData(); meaning that internalData is still an empty array when this statement gets processed.

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?