关于IE下AJAX的问题探讨
程序员文章站
2023-11-07 17:45:58
今天js练手的时候,想封装一个发送ajax请求的对象,当然,是想要兼容全浏览器的。代码如下: 复制代码 代码如下: var ajax = { xhr: null, call...
今天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对象。故造成了我这次的“事故”。
复制代码 代码如下:
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对象。故造成了我这次的“事故”。
上一篇: php生成shtml类用法实例
下一篇: 孕妇能喝生姜汁吗,姜汁的功效和作用