AjaxPro 内部机制探讨
前面我们看到了 this.xmlHttp 大显神威。那么它是哪儿来的?看看 AjaxPro.Request 类的 initialize 函数吧(有删节):
2 this.xmlHttp = new XMLHttpRequest();
3}
4
是了,xmlHttp 只是 XMLHttpRequest 的一个实例。那么 XMLHttpRequest 的定义呢?
2if(!window.XMLHttpRequest) {
3
4 function getXmlHttp(clsid) {
5 var xmlHttp = null;
6 try {
7 xmlHttp = new ActiveXObject(clsid);
8 lastclsid = clsid;
9 return xmlHttp;
10 } catch(ex) {}
11 }
12
13 window.XMLHttpRequest = function() {
14 if(lastclsid != null) {
15 return getXmlHttp(lastclsid);
16 }
17
18 var xmlHttp = null;
19 var clsids = ["Msxml2.XMLHTTP.6.0","Msxml2.XMLHTTP.5.0","Msxml2.XMLHTTP.4.0","Msxml2.XMLHTTP.3.0","Msxml2.XMLHTTP.2.6","Microsoft.XMLHTTP.1.0","Microsoft.XMLHTTP.1","Microsoft.XMLHTTP"];
20
21 for(var i=0; i<clsids.length && xmlHttp == null; i++) {
22 xmlHttp = getXmlHttp(clsids[i]);
23 }
24
25 if(xmlHttp == null) {
26 return new IFrameXmlHttp();
27 }
28
29 return xmlHttp;
30 }
31}
32
哦,原来是在这里真正创建的。说到底还是一个 ActiveXObject 啊。关于这个本文也不再多提。不过代码中还需要注意的一点是,
如果把第19行列出的一大堆clsids 都处理过了还没有得到对象怎么办?注意到第26行 new 了一个 IFrameXmlHttp。
IFrameHttp 是在 core.ashx 中定义的,它基本上完全模拟了 ActiveXObject 对象的功能。想研究研究的,自己看源码吧。篇幅所限,这里不多讲啦。
八、doStateChange 函数
嗯,前面已经提过,异步的话 doStateChange 函数将会在服务端返回后执行,看看它的源码呢:
2 if(this.onStateChanged != null && typeof this.onStateChanged == "function")
3 try{ this.onStateChanged(this.xmlHttp.readyState); }catch(e){}
4
5 if(this.xmlHttp.readyState != 4)
6 return;
7
8 if(this.xmlHttp.status == 200) {
9 if(this.timeoutTimer != null) clearTimeout(this.timeoutTimer);
10 if(typeof this.onLoading == "function") this.onLoading(false);
11
12 this.xmlHttp.onreadystatechange = AjaxPro.noOperation;
13
14 this.callback(this.createResponse());
15 this.callback = null;
16
17 this.xmlHttp.abort();
18 }
19},
20
如果 status 是 200,也就是 OK,那么清除掉超时处理函数,处理 onLoading 事件,最后使用 callback 调用 createResponse 函数。还记得如果不是异步的话,createResponse 将会直接调用而不是通过 doStateChange 吧。
九、createResponse 函数
2 var r = new Object();
3 r.error = null;
4 r.value = null;
5
6 var responseText = new String(this.xmlHttp.responseText);
7
8 if(AjaxPro.cryptProvider != null && typeof AjaxPro.cryptProvider == "function")
9 responseText = AjaxPro.cryptProvider.decrypt(responseText);
10
11 eval("r.value = " + responseText + ";");
12
13 if(r.error != null && this.onError != null && typeof this.onError == "function")
14 try{ this.onError(r.error); }catch(e){}
15
16 responseText = null;
17
18 return r;
19}
如果前面的 json 也就是 Request 是加过密的,这里就需要对 responseText 进行解密。完了之后得到 r.value,r 将会被返回并提供给 callback 函数。本例中将最终传回 doTest1_callback,r 被传入它的 res 参数。最后更新文本框下的字符串,整个 Ajax ClientScript 的流程就差不多是完成了。
十、简单总结一下
呼,长出一口气。总算可以告一段落了,AjaxPro 服务端的拆解过段时间再说吧。
在分析 ClientScript 端的时候真是大有感触,JavaScript 其实远比人们想象的强大和管用。其实我同大多数人一样,起初也对它很不感冒,但是之前曾有两件事让我改变了观念。其一是阅读了黄忠成的《深入剖析 ASP.NET 组件设计》,才发现原来许多强大炫目的 ASP.NET 的控件,其实都是用的 JavaScript 实现。其二是在研究国外某文档浏览器实现的时候,发现人家使用 JavaScript 在 IE 下相当完美地实现了强大灵活有如桌面程序的界面和功能,真是吃惊不小。当时就发现了自己对 JavaScript 的了解实在是严重汗颜,惭愧无地。无奈平时没有多少时间去学习提高自己,只能偶尔抽抽空余时间了解了解,充充电吧。
相信 JavaScript 之类的脚本必将在未来的 Web 应用中大展身手。