AjaxPro 内部机制探讨
前面我们看到了 this.xmlHttp 大显神威。那么它是哪儿来的?看看 AjaxPro.Request 类的 initialize 函数吧(有删节):

initialize: function(url)
{2
this.xmlHttp = new XMLHttpRequest();3
}4

是了,xmlHttp 只是 XMLHttpRequest 的一个实例。那么 XMLHttpRequest 的定义呢?
var lastclsid = null;2

if(!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 函数将会在服务端返回后执行,看看它的源码呢:

doStateChange: function()
{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 函数

createResponse: function()
{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 应用中大展身手。