我正在开发一个简单的辅助类来使用XmlHttpRequest发送请求(下面的代码)。但我不能让它发挥作用。例如,在谷歌浏览器中,我收到错误INVALID_STATE_ERR: DOM Exception 11
,而在其他浏览器中,我获得状态== 0。
//@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) {
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;
case "setHeader":
var h = args[e].split(":");
if(h.length == 2) {
this.SetRequestHeader(h[0], h[1]);
}
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);
this.XHR.send(body);
}
使用示例:
<script language="javascript">
function onLoad() {
var x = XRequest.GetInstance();
x.SendRequest({type:"GET",
setHeader:"Accept:text/html, image/png, image/*, */*",
url: "http://your_server.com/getData?param1=test",
success:onSuccess, failure:onFail
});
}
function onSuccess(obj) {
alert("OK");
}
function onFail() {
alert("Not at this time!");
}
</script>
答案 0 :(得分:40)
这个ajax库存在问题。
必须在XHR.setRequestHeader()
之后调用{p> 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);
}
答案 1 :(得分:9)
无论如何,您可以通过创建mixin而不是使用巨型SendRequest
来简化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);
};
另外要小心:现有的for..in
循环有两个明显的问题:
var
并导致创建全局:for (e in args)
应为for (var e in args)
for..in
时,您应该始终检查以确保每个键都是该对象的直接成员,而不是通过原型无意中继承的内容
for ( var i in obj ) {
if ( obj.hasOwnProperty(i) ) {
// do stuff here
}
}
答案 2 :(得分:6)
通常,当您使用async = true调用open方法时,XMLHttpRequest会发生此错误,或者您将async参数保留为undefined,因此默认为异步,然后您可以访问status或responseText属性。这些属性仅在您执行同步调用后或readyState准备就绪时(异步调用响应时)可用。我建议你首先尝试使用async = false,然后切换到true并使用onReadyStateChange。
答案 3 :(得分:3)
在我的情况下,当我尝试在xhr.statusText
方法中访问xhr.onreadystatechange
时发生了错误,但是检索xhr.readyState
就没问了。