首页 > 代码库 > 关于IE下AJAX的问题探讨

关于IE下AJAX的问题探讨

今天JS练手的时候,想封装一个发送AJAX请求的对象,当然,是想要兼容全浏览器的。代码如下: 

var Ajax = { 
xhr: null, 
callback: null, 
XMLHttp: function() { 
var xmlhttp; 
//标准浏览器 
if(window.XMLHttpRequest) { 
try { 
xmlhttp = new XMLHttpRequest(); 
} 
catch(e) { 
alert(‘Unknown Ajax Error‘); 
//console.log(‘Unknown Ajax Error‘); 
} 
} 
//IE浏览器 
else { 
if(window.ActiveXObject) { 
try { 
xmlhttp = new ActiveXObject(‘Microsoft.XMLHTTP‘); 
} 
catch(e) { 
try { 
xmlhttp = new ActiveXObject(‘MSXML2.XMLHTTP‘); 
} 
catch(e) { 
alert(‘Unknown Ajax Error‘); 
//console.log(‘Unknown Ajax Error‘); 
} 
} 
} 
} 
return xmlhttp; 
}, 
connect: function(paramsObj) { 
var PO = paramsObj; 
//判断传参合法性 
if(!(PO instanceof Object)) { 
alert(‘Ajax params illegal‘); 
//console.log(‘Ajax params illegal‘); 
return false; 
} 
else if(!(PO.url&&PO.method&&PO.callback)) { 
return false; 
} 
//初始化内部参数 
this.xhr = this.XMLHttp(); 
this.callback = PO.callback; 
//遍历params对象并生成url参数 
var requestParams = ‘‘; 
if(PO.params) { 
for(key in Po.params) { 
requestParams += ‘&‘ + key + ‘=‘ + params[key]; 
} 
requestParams = requestParams.substr(1); 
} 
//发起Ajax请求 
try { 
var xhr = this.xhr; 
xhr.onreadystatechange = this.response; 
//POST请求处理 
if(PO.method.toLowerCase()==‘post‘) { 
xhr.open(‘POST‘,PO.url,true); 
xhr.send(requestParams); 
} 
//GET请求处理 
else if(PO.method.toLowerCase()==‘get‘) { 
xhr.open(‘GET‘,PO.url+‘?‘+requestParams,true); 
xhr.send(null); 
} 
} 
catch(e) { 
this.callback(null,-1); 
} 
}, 
response: function() { 
// 此段代码在全浏览器下测试通过 
// if(Ajax.xhr.readyState==4) { 
// if(Ajax.xhr.status==‘200‘) { 
// Ajax.callback(Ajax.xhr.responseText); 
// } 
// else { 
// Ajax.callback(null,Ajax.xhr.status); 
// } 
// } 
// 
// 下面的代码在IE下失效(无报错,请求有相应,却没有返回结果),其它浏览器无此问题 
if(this.readyState==4) { 
if(this.status==‘200‘) { 
Ajax.callback(this.responseText); 
} 
else { 
Ajax.callback(null,this.status); 
} 
} 
} 
}; 

//Ajax实例 
Ajax.connect({ 
url: ‘test.html‘, 
method: ‘GET‘, 
callback: function(data,err) { 
if(data!=null) { 
alert(data); 
// console.log(data); 
} 
else { 
alert(err); 
// console.log(err); 
} 
} 
}); 

 


问题描述: 大家看一下我代码中有一块注释掉的代码,那块代码是在全浏览器下测试通过的。而没有注释掉的代码是有问题的代码,具体表现: 

在Chrome,Firefox,Opera,Safari下测试通过,在IE6、7(IE8+没有测试)下的表现是:没有报错,也没有返回结果。 

对比上下两块代码的不同,我想有两个可能,一个是this指向的问题,一个是IE下onreadystatechange函数执行的上下文环境有区别于其它浏览器。但是现在又无法确定问题,IE6、7下的JS调试又挺困难的(试了firebug-lite,但是没有想象中的好用,而且这个Ajax对象在firebug-lite下调用却成功了,有点糊涂) 
解决过程: 

其实测试方法很简单。主要是头脑一发热没想到,吃了个饭回来就恍然大悟。 

其实JS在处理this指向不明的问题的时候,可以尝试使用this instanceof Object这类判断去了解它指向的是一个什么类型的变量。而对于判断是否为全局调用,则可以使用this===window。在这里我用的就是这个方法。 

在代码出现问题的那一块,我们可以试着插入一段: 

alert(this instanceof Object); 

结果发现,在IE6下,返回为false!一目了然!在IE下才可能出现如此诡异的返回值!证明什么?也就是说函数的执行上下文并非是对象!如此一来,在IE下就只能想到window对象了,要知道IE向来都是奇葩。你们标准浏览器说window对象是对象,我就偏不认。你还在怀疑我的看法?那何不试试? 

alert(this===window); 

结果是true!怎么样?没话说了吧?所以这样,问题就明朗了: 

在IE下,AJAX请求得到响应后,回调函数onreadystatechange是在全局环境下被调用的。而在标准浏览器下,其执行上下文是XMLHttpRequest对象。故造成了我这次的“事故”。

<iframe id="google_ads_frame2" vspace="0" height="250" marginHeight="0" src="http://googleads.g.doubleclick.net/pagead/ads?client=ca-pub-3447371224873639&output=html&h=250&slotname=8660799060&adk=1970350646&w=300&lmt=1398862271&flash=11.9.900.117&url=http%3A%2F%2Fwww.cnblogs.com%2Fxiaochao12345%2Fp%2F3700993.html&dt=1398862249758&shv=r20140424&cbv=r20140417&saldr=sb&prev_slotnames=4356862740&correlator=1398862249644&frm=20&ga_vid=429972749.1397695120&ga_sid=1398816550&ga_hid=986631767&ga_fc=1&u_tz=480&u_his=827&u_java=1&u_h=768&u_w=1364&u_ah=740&u_aw=1364&u_cd=16&u_nplug=0&u_nmime=0&dff=verdana&dfs=12&adx=0&ady=0&biw=314&bih=74&eid=317150304&oid=3&rx=0&eae=0&docm=9&vis=0&fu=0&ifi=2&xpc=tRXaLCvicu&p=http%3A//www.cnblogs.com&dtd=49" frameBorder="0" width="300" allowTransparency="true" name="google_ads_frame2" marginWidth="0" scrolling="no" hspace="0"></iframe><iframe id="google_ads_frame3" vspace="0" height="250" marginHeight="0" src="http://googleads.g.doubleclick.net/pagead/ads?client=ca-pub-3447371224873639&output=html&h=250&slotname=8660799060&adk=1970350646&w=300&lmt=1398862271&flash=11.9.900.117&url=http%3A%2F%2Fwww.cnblogs.com%2Fxiaochao12345%2Fp%2F3700993.html&dt=1398862249815&shv=r20140424&cbv=r20140417&saldr=sb&prev_slotnames=4356862740%2C8660799060&correlator=1398862249644&frm=20&ga_vid=429972749.1397695120&ga_sid=1398816550&ga_hid=986631767&ga_fc=1&u_tz=480&u_his=827&u_java=1&u_h=768&u_w=1364&u_ah=740&u_aw=1364&u_cd=16&u_nplug=0&u_nmime=0&dff=verdana&dfs=12&adx=304&ady=250&biw=314&bih=74&eid=317150304&oid=3&rx=0&eae=0&docm=9&vis=0&fu=0&ifi=3&xpc=0eq2RtQpo9&p=http%3A//www.cnblogs.com&dtd=48" frameBorder="0" width="300" allowTransparency="true" name="google_ads_frame3" marginWidth="0" scrolling="no" hspace="0"></iframe>