I\'m developing a simple auxiliary class to send requests using XmlHttpRequest (code below). But I cant make it work. At google chrome, for example, I get the error INVALI
Usually this error occurs with the XMLHttpRequest when you call the open method with async = true, or you leave the async parameter undefined so it defaults to asynchronous, and then you access the status or responseText properties. Those properties are only available after you do a synchronous call, or on the readyState becoming ready (once the asynchronous call responds). I suggest you first try with async = false, and then switch to it being true and use the onReadyStateChange.
Problem in this ajax library.
XHR.setRequestHeader()
must be called after XHR.open()
.
// @method XRequest: Object constructor. As this implements a singleton, the object can't be created calling the constructor, GetInstance should be called instead
function XRequest()
{
this.XHR = XRequest.CreateXHR();
}
XRequest.instance = null;
// @method static GetInstance: Creates a singleton object of type XRequest. Should be called whenever an object of that type is required.
// @return: an instance of a XRequest object
XRequest.GetInstance = function()
{
if(XRequest.instance == null)
{
XRequest.instance = new XRequest();
}
return XRequest.instance;
}
// @method static CreateXHR: Implments a basic factory method for creating a XMLHttpRequest object
// @return: XMLHttp object or null
XRequest.CreateXHR = function()
{
var xhr = null;
var factory = [
function() { return new XMLHttpRequest(); },
function() { return new ActiveXObject("Msxml2.XMLHTTP"); },
function() { return new ActiveXObject("Microsoft.XMLHTTP"); }
];
for(var i = 0; i < factory.length; ++i)
{
var f = factory[i];
xhr = f();
if(xhr)
return xhr;
}
return null;
}
XRequest.prototype.SetRequestHeader = function(name, value)
{
if(this.XHR)
{
//alert(name+'|||'+value);
this.XHR.setRequestHeader(name, value);
}
}
XRequest.prototype.SendRequest = function(args)
{
var async = true;
var type = "";
var url = "";
var username = "";
var password = "";
var body = null;
var success = null;
var failure = null;
for(e in args)
{
switch(e)
{
case "async":
async = args[e];
break;
case "type":
type = args[e];
break;
case "success":
success = args[e];
break;
case "failure":
failure = args[e];
break;
case "url":
url = args[e];
break;
case "username":
username = args[e];
break;
case "password":
password = args[e];
break;
case "body":
body = args[e];
break;
}
}
var that = this;
this.XHR.onreadystatechange = function()
{
alert("readyState == " + that.XHR.readyState + " status == " + that.XHR.status);
if(that.XHR.readyState == 4)
{
if(that.XHR.status == 200 || that.XHR.status == 0)
{
if(success)
success(that.XHR);
}
else
{
if(failure)
failure();
}
}
};
this.XHR.open(type, url, async, username, password);
for(e in args)
{
switch(e)
{
case "setHeader":
var h = args[e].split(":");
if(h.length == 2)
{
this.SetRequestHeader(h[0], h[1]);
}
break;
}
}
this.XHR.send(body);
}
In my case the error occurred when i tried to access xhr.statusText
within the xhr.onreadystatechange
method, however retrieving xhr.readyState
went just fine.
Regardless, you can simplify your SendRequest
method by creating a mixin instead of using a giant switch
.
XRequest.prototype.SendRequest = function(params) {
var defaultParams = {
async: true,
type: "",
url: "",
username: "",
password: "",
body: null,
success: null,
failure: null
};
for ( var i in defaultParams ) {
if ( defaultParams.hasOwnProperty(i) && typeof params[i] == "undefined" ) {
params[i] = defaultParams[i];
}
}
var that = this;
this.XHR.onreadystatechange = function() {
if ( that.XHR.readyState == 4 ) {
if ( that.XHR.status == 200 || that.XHR.status == 0 ) {
if ( params.success ) {
params.success(that.XHR);
}
} else {
if ( params.failure ) {
params.failure();
}
}
}
};
this.XHR.open(
params.type, parms.url, params.async, params.username, params.password
);
// It doesn't make sense to have a for/switch here when you're only handling
// one case
if ( params.setHeader ) {
var h = params.setHeader.split(":");
if ( h.length == 2) {
this.SetRequestHeader(h[0], h[1]);
}
}
this.XHR.send(params.body);
};
Also be careful: your existing for..in
loops have two distinct problems:
var
and causing a global to be created: for (e in args)
should be for (var e in args)
for..in
, you should always check to make sure that each key is a direct member of the object, and not something inherited inadvertently through prototype.
for ( var i in obj ) {
if ( obj.hasOwnProperty(i) ) {
// do stuff here
}
}