views:

863

answers:

3

I am trying to create a Firefox extension that can run multiple XMLHttpRequests per page. The code is below (my main function calls the makeRequest on different URLs). My problem is that it always returns (at the "alert('Found ...')" for debugging purposes) the same URL instead of displaying the different responses. I think the issue is that I should somehow pass the http_request instance to the alertContents() function instead of just using http_request directly, but not sure how or if this is correct. Thank you.

function makeRequest(url,parameters) {
   http_request = false;
   http_request = new XMLHttpRequest();
   if (http_request.overrideMimeType) {
   http_request.overrideMimeType('text/xml');
   }
   if (!http_request) {
   alert('Cannot create XMLHTTP instance');
   return false;
   }
   http_request.onreadystatechange = alertContents;
   http_request.open('GET', url + parameters, true);
   http_request.send(null);

}

function alertContents() {
   if (http_request.readyState == 4) {
   if (http_request.status == 200) {
   alert('Found: ' + http_request.responseText);
   } else {
   alert('There was a problem with the request.');
   }
   }
}
A: 

Yes, you should use the same XMLHttpRequest.

Infact, try using this code and see if it works :

function makeRequest(url,parameters) {
   http_request = false;
   http_request = new XMLHttpRequest();
   if (http_request.overrideMimeType) {
          http_request.overrideMimeType('text/xml');
   }
   if (!http_request) {
          alert('Cannot create XMLHTTP instance');
          return false;
   }
   http_request.onreadystatechange = function () {
       if (http_request.readyState == 4) {
          if (http_request.status == 200) {
                        alert('Found: ' + http_request.responseText);
          } else {
                 alert('There was a problem with the request.');
          }
       }
   };
   http_request.open('GET', url + parameters, true);
   http_request.send(null);
}

In the code above, I simply attached the function directly to the onreadystatechange event .

Andreas Grech
This still has the issue that only one http_request identifier exists, the http_request is not var'ed
AnthonyWJones
+2  A: 

Your problem is you've only got one http_request identifier which is reused every time the makeRequest function is called. Here is one simple adjustment:-

function makeRequest(url,parameters) {
   var http_request = new XMLHttpRequest();
   if (http_request.overrideMimeType) {
   http_request.overrideMimeType('text/xml');
   }
   if (!http_request) {
   alert('Cannot create XMLHTTP instance');
   return false;
   }
   http_request.onreadystatechange = function() { 
           alertContents(http_request)
       };
   http_request.open('GET', url + parameters, true);
   http_request.send(null);
       return http_request;
}

function alertContents(http_request) {
   if (http_request.readyState == 4) {
   if (http_request.status == 200) {
   alert('Found: ' + http_request.responseText);
   } else {
   alert('There was a problem with the request.');
   }
              http_request.onreadystatechange = fnNull;
   }
}

    function fnNull() { };

The http_request identifier is local to each makeRequest execution. The correct instance of XHR is then passed to alerrContents each time onreadystatechange is fired by using a capture.

BTW, why separate url from parameters? Since the caller has to ensure the parameters argument is correctly url encoded it doesn't seem like a very useful abstraction. In addition the caller can simply pass a URL containing a querystring anyway.

AnthonyWJones
That really helped. Thanks!Agreed - the abstraction only makes it slightly easier on me - not really necessary.
GavinR
A: 

this function can be further improved with cross browser functionality:

function makeRequest(method, url, parameters) {
    var http_request = false;
    if (window.XMLHttpRequest) { // Mozilla, Safari,...
        http_request = new XMLHttpRequest();
        if (http_request.overrideMimeType) {
            // set type accordingly to anticipated content type
            http_request.overrideMimeType('text/xml');
            //http_request.overrideMimeType('text/html');
        }
    } else if (window.ActiveXObject) { // IE
        try {
            http_request = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
        try {
            http_request = new ActiveXObject("Microsoft.XMLHTTP");
        } catch (e) {}
        }
    }
    if (!http_request) {
        alert('Cannot create XMLHTTP instance');
        return false;
    }
    http_request.onreadystatechange = function() {
        alertContents(http_request);
    }
    url += (method=="GET")?parameters:"";
    http_request.open(method, url, true);
    if (method == "POST") {
        http_request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        http_request.setRequestHeader("Content-length", parameters.length);
        http_request.setRequestHeader("Connection", "close");
    }
    http_request.send((method=="GET")?null:parameters);
}
Greywacke