Acrobatics with JavaScript

I don’t think I have ever felt so comfortable working with a language at work. Javascript is incredibly expressive, and adapts to the implementation of my needs on a per project basis quite well. In that way, JS lends itself to being used in interesting and evolving ways on the same project.

Some are good others are horrible, some should be fucking illegal.

Async. Event Handling

I am responsible for maintaining a lump of patchwork that is considered the mobile web SDK, the idea being that people website owners, or publishers, should be able to incorporate ads into their website without having to bother learning some new bullshit and without having too much complication, and above all else we have to make sure they are trafficked and tracked appropriately – they should be kept out of that. I am a firm believer in in-sourcing projects that are important to your business, and so here I am.

We have a number of very odd behavior coming from our event tracking, like when the first quartile event arrives after the third quartile or completion events, so clearly something was up. I spent some time thinking it through and well, asynchronous JavaScript comes to the rescue.

Our events are tracked by a series of URLs that need to be hit, and we don’t really care for the response or confirmation, if our sites go down things will be known well before people ask about tracking data, and there are backups I also don’t worry about. Anyways, I came up with a cascading request manager that handles things:

var requestManager = (function () 
{
    var RequestManager = function () 
    {
    };

    RequestManager.prototype.RequestInProgress = false;
    RequestManager.prototype.CurrentRequest = null;
    RequestManager.prototype.RequestsQueue = [];
    RequestManager.prototype.Execute = function (url, callback) {
        var rm = this;

        if (rm.RequestInProgress !== false)
        {
            rm.RequestsQueue.push({url: url, callback: callback});
            // console.log("Request in progress");
            return null;
        }

        rm.RequestInProgress = true;

        rm.CurrentRequest = new XMLHttpRequest();

        rm.CurrentRequest.onreadystatechange = function (response)
        {
            if (response.target.readyState != 4)
                return;

            rm.RequestInProgress = false;  

            if (typeof(callback) !== "undefined")
                callback(response);

            if (rm.RequestsQueue.length > 0)
            {
                var tmp = rm.RequestsQueue.shift();
                rm.Execute(tmp.url, tmp.callback);
            }
        };

        rm.CurrentRequest.open("GET", url, false);
        rm.CurrentRequest.send();

        return rm.CurrentRequest;
    };

    return new RequestManager();
})();

Sure it isnt the most efficient design for an example possible, but the cascading request format is as useful as a semicolon in this environment. The kicker is the way that it handles events. An XmlHTTPRequest is created, its destination is set and then we monitor the results of the request. Once the request is completed, readystate == 4, we hand off the response to a user defined callback and check to see if there is a new request to be made. If there is we spin up a new request and send it along the exact same flow.

requestManager.Execute(url, function (response) {});

This an example of the usage, hiding some of the complication. The idea is to be able to execute this function call an it arbitrary number of times, and ensure that the requests are eventually executed.

If you happened to be needing something like this, enjoy. Otherwise, feel free to enjoy its simplicity.