最近遇到一个问题,ie6下js可用,但用AJAX做异步请求的时候总是失败,用的是jQuey封装的,报的错误是: Error:Automation 服务器不能创建对象 。查找后发现原来是客户将Internet选项里的安全设置过高,将“对标记为可安全执行的ActiveX控件执行脚本“设置为禁用造成的。
先来看下jQuery中关于创建XHR对象的代码:
jQuery.js
var xhr = window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
此时的 typeof window.ActiveXObject会返回一个function ,但new ActiveXObject("Microsoft.XMLHTTP")时就会产生上面的异常,问题到此基本知道原因了,本着举一反三的精神,找了下其他js框架创建XHR对象的方法
prototype.js
var Ajax = { getTransport: function() { return Try.these( function() {return new XMLHttpRequest()}, function() {return new ActiveXObject('Msxml2.XMLHTTP')}, function() {return new ActiveXObject('Microsoft.XMLHTTP')} ) || false; }, activeRequestCount: 0 };
mootools.js
Browser.Request = function(){ return $try(function(){ return new XMLHttpRequest(); }, function(){ return new ActiveXObject('MSXML2.XMLHTTP'); }); };
dojo.js
d._XMLHTTP_PROGIDS = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0']; d._xhrObj = function(){ // summary: // does the work of portably generating a new XMLHTTPRequest // object. var http = null; var last_e = null; if(!dojo.isIE || !dojo.config.ieForceActiveXXhr ){ try{ http = new XMLHttpRequest(); }catch(e){} } if(!http){ for(var i=0; i<3; ++i){ var progid = d._XMLHTTP_PROGIDS[i]; try{ http = new ActiveXObject(progid); }catch(e){ last_e = e; } if(http){ d._XMLHTTP_PROGIDS = [progid]; // so faster next time break; } } } if(!http){ throw new Error("XMLHTTP not available: "+last_e); } return http; // XMLHTTPRequest instance }
关于 dojo.config.ieForceActiveXXhr
//Workaround to get local file loads of dojo to work on IE 7 //by forcing to not use native xhr. if(dojo.isIE && window.location.protocol === "file:"){ dojo.config.ieForceActiveXXhr=true; }
关于window.location.protocol
The URL protocol section including the colon after the protocol name. The values are normally http: or file:. The following JavaScript code may be used to identify the source of the URL. switch (window.location.protocol) { case "http:": document.write("From Web<BR>\n") break case "file:": document.write("From Local computer<BR>\n") break default: document.write("Unknown Source<BR>\n") break }
这里需要解释下,从ie7开始加入了对原生的XMLHttpRequest的支持,即ie7以后的版本中对于XHR对象的创建即可以通过ActiveXObject也可以通过直接的new XMLHttpRequest()实现,但是出于安全考虑, ie7的原生XHR是不支持本地使用的,所以在这段js中如果检测但浏览器版本是ie7并且是本地请求创建XHR对象则还是用ActiveXObject来实现的。
(这个细节就是体现js框架差距的地方吧 O(∩_∩)O)
YUI:
connection.js /* _msxml_progid:[ 'Microsoft.XMLHTTP', 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP' ] */ createXhrObject:function(transactionId) { var obj,http; try { // Instantiates XMLHttpRequest in non-IE browsers and assigns to http. http = new XMLHttpRequest(); // Object literal with http and tId properties obj = { conn:http, tId:transactionId }; YAHOO.log('XHR object created for transaction ' + transactionId, 'info', 'Connection'); } catch(e) { for(var i=0; i<this._msxml_progid.length; ++i){ try { // Instantiates XMLHttpRequest for IE and assign to http http = new ActiveXObject(this._msxml_progid[i]); // Object literal with conn and tId properties obj = { conn:http, tId:transactionId }; YAHOO.log('ActiveX XHR object created for transaction ' + transactionId, 'info', 'Connection'); break; } catch(e2){} } } finally { return obj; } }
关于{'Microsoft.XMLHTTP','MSXML2.XMLHTTP.3.0','MSXML2.XMLHTTP','Msxml2.XMLHTTP.4.0' ...}这些proGid的区别以及为什么框架们要一遍一遍的去尝试的意义请参考
Difference between MSXML2.XmlHttp and Microsoft.XmlHttp ProgIDs
(微软真的害人啊 )
对比这5个主流的框架可以从代码风格上看出点东西:
1)jQuery受欢迎是有道理的:能一行代码搞定的东西,用起来学起来都方便,即使偶然极端情况下会出错,可我们的原则就是花最少精力去解决大部分的问题,剩下的一小部分问题,交给那20%倒霉的程序员吧。
2)相互借鉴,发扬光大,站在巨人的肩膀上...都很适合开源的。
3)想做大做强就必须有条条框框的束缚。(所以还是喜欢jquery的简单)
3) Dojo应该是最开发者体验的框架了,甚至读它的源码能扩展一连串的知识,佩服ing,在fireBug控制台下看dojo的类库唰唰的加载多好玩啊:-D
附件是对于上述几个框架的AJAX简单测试的demo,带各个框架的源码,可当个简易教程,并附加DojoToolbox.air
方便想了解的的同学们~~O(∩_∩)O