TobyRush TobyRush - 4 months ago 8
Ajax Question

How do I manage multiple, overlapping XMLHttpRequests?

I'm working on my first AJAX project, and I've started by setting up the following functions:

function sendHTTPRequest(callback,filename,data) {

if (window.XMLHttpRequest) {
httpRequest = new XMLHttpRequest();
} else if (window.ActiveXObject) {
httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
}

httpRequest.onreadystatechange = callback;
httpRequest.open('POST',rootAddress+filename, true);
httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
httpRequest.send(data);

}

function exampleCallback() {

if (httpRequest.readyState === XMLHttpRequest.DONE) {
if (httpRequest.status === 200) {
// successful, parse the XML data
} else {
// error
}
} else {
// not ready
}
}


This has worked well but I've now gotten to the point where I have more than one simultaneous HTTP request, and my single global
httpRequest
variable isn't cutting it. It seems to me I could use an array, and
.push
a new XMLHttpRequest onto the stack each time
sendHTTPRequest()
is called, but how can I tell my various callback functions which item in the stack to parse? Or is the a better way to handle this process? (I'm using these to handle requests to different pages, with results that need to be parsed differently.)

Thanks!

Answer

Use a local variable and a per-request callback, which in turn calls the given callback. The changes required are surprisingly small; see ** lines:

function sendHTTPRequest(callback,filename,data) {
    var httpRequest; // ** Local variable

    if (window.XMLHttpRequest) {
        httpRequest = new XMLHttpRequest();
    } else if (window.ActiveXObject) {
        httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
    }

    // ** Callback specific to *this* request
    httpRequest.onreadystatechange = function() {
        if (httpRequest.readyState === XMLHttpRequest.DONE) {
            if (httpRequest.status === 200) {
                // successful, call the callback
                callback(httpRequest);
            } else {
                // error, call the callback -- here we use null to indicate the error
                callback(null);
            }
        } else {
            // not ready
        }
    };
    httpRequest.open('POST',rootAddress+filename, true);
    httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    httpRequest.send(data);
}

function exampleCallback(xhr) {

    if (xhr) {
        // successful, parse the XML data, for instance
        var x = xhr.responseXML;
    } else {
        // not ready
    }
}

You could have it give the callback more information (for instance, the filename and data arguments).

If you use promises, you could have sendHTTPRequest return a promise instead of accepting a direct callback.

Comments