AjaxPro 内部机制探讨

  应当承认我这人实在算不上弄潮儿,Ajax 早已流行得一塌糊涂,我却始终没有来研究一下这个东东。上次做网站的时候,BOSS 就跟我讲过,可以参考一下 Ajax 的技术,我嘴上答应,心里却不是十分的在乎。究其原因,一来是我这人比较固步自封,二来起初确实也没太相信 Ajax 真有 BOSS 说的那么神奇。

  转变是从昨天天始的,这一周在公司主要精力都是在用 C++ 写 framework,不得不承认它比较辛苦,细枝末节之处非常之烦,昨天下午呆着呆着就不想干活了,就开始四处游荡,正好看到我们自己也有项目已经成功应用了 Ajax,于是也就想看一看,无奈那帮家伙的开发文档是出奇的少,只好在网上找找资料,自己研究研究吧。

  作为一个技术人员,我看到一项新技术,总是喜欢琢磨琢磨它内部是如何实现的。在对 Ajax 有了初步认识以后,自然想看看其内部机制,但是令我失望的是,至少介绍 Ajax 内部实现的文章少之又少,好容易找到一篇,却也只是简单列了列一些 Javascript 代码,并且没什么解释,颇为郁闷。想想求人不如求己,况且自己研究的或许印象更深一些。于是找到了一个 AjaxPro,下来琢磨琢磨,只是对于 JavaScript 我实在知之甚少,不明白之处依然很多,不过还是想写出来,抛砖引玉,望高人们不吝指教。

  一、使用的例子

  本文使用的例子很简单,一个文本框,在其中敲入文字之后,下方就显示该文字并加上一个“(Hello from server)”。源码如下(有删节):

 1<%@ Page language="c#" ClassName="KeyPressDemo" Inherits="System.Web.UI.Page" %>
 2<script runat="server" language="c#">
 3
 4private void Page_Load(object sender, EventArgs e)
 5{
 6    AjaxPro.Utility.RegisterTypeForAjax(typeof(KeyPressDemo));
 7}

 8
 9[AjaxPro.AjaxMethod]
10public string EchoInput(string s)
11{
12    return s += " (Hello from server)";
13}

14
15
script>
16
17<form id="Form1" method="post" runat="server">form>
18
19<div class="content">
20<h1>KeyPressDemo Examplesh1>
21<p>Press any key in the textbox and see the echo in the DIV element on the right side.p>
22<input type="text" id="myinput" onkeyup="doTest1();"/> <div id="mydisplay">---- empty ----div>
23<p><i>Note, that I do not update the display if a request is running currently.i>p>
24div>
25
26<script type="text/Javascript" defer="defer">
27
28var timer = null;
29
30function doTest1() {
31    if(timer != null{
32      clearTimeout(timer);
33    }

34    timer = setTimeout(doTest1_next, 100);
35}

36
37function doTest1_next() {
38    var ele = document.getElementById("myinput");
39    ASP.KeyPressDemo.EchoInput(ele.value, doTest1_callback);
40}

41
42function doTest1_callback(res) {
43    var ele = document.getElementById("mydisplay");
44    ele.innerHTML = res.value;
45}

46
47
script>
  二、Ajax ClientScript 的执行总体流程

  好,有了源页面代码,又有了两个 ClientScript 文件,我们就可以分析客户端的执行流程了。以下是我画的一张简单的流程图:



  我们一个一个地来分析。

  三、HTML页面做了什么?

  第一步,当我们在 TextBox 里输入字符后,将会触发 onkeyup 事件。它要执行 doTest1 方法。见页面代码里的第22行。

  第二步,doTest1 方法使用 setTimeout 函数,设定了 100 毫秒后,执行 doTest1_next 方法。见页面代码里的第34行。

  第三步,doTest1_next 方法调用了 ASP.KeyPressDemo.EchoInput 方法,它带有两个参数,第一个是我们在文本框中输入的值,当然是个字符串类型的了;第二个则是一个 callback 函数,请留心这个函数,它将于整个流程的最后执行。

  好,我们知道页面的客户端无外乎就是 HTML 和 JavaScript,虽然 ASP.KeyPressDemo.EchoInput 方法酷似页面里我们自己用 C# 写的函数,但可以肯定的是它绝对是用 JavaScript 实现的。在哪儿呢?嗯,在我们从 Temporary InterNET Files 目录下找到的 ASP.KeyPressDemo,App_Web_vxhzzzxr.ashx 里。

  四、ASP.KeyPressDemo,App_Web_vxhzzzxr.ashx 的实现

  这个文件很小,以下是它的全部源码:

 1addNamespace("ASP");
 2ASP.KeyPressDemo_class = Class.create();
 3ASP.KeyPressDemo_class.prototype = (new AjaxPro.Request()).extend({
 4    EchoInput: function(s, callback) {
 5        return this.invoke("EchoInput"{"s":s}, callback);
 6    }
,
 7    initialize: function() {
 8        this.url = "/ajaxdemo/ajaxpro/ASP.KeyPressDemo,App_Web_vxhzzzxr.ashx";
 9    }

10}
)
11ASP.KeyPressDemo = new ASP.KeyPressDemo_class();
12  五、Invoke 函数

  Invoke 函数是核心所在,前面我画的流程图中已经简单地描述了它的主要流程。不过这个函数太重要了,这里还是列出它的全部源码:

 1AjaxPro.Request = Class.create();
 2AjaxPro.Request.prototype = (new AjaxPro.Base()).extend({
 3    invoke: function(method, data, callback) {
 4        var async = typeof callback == "function" && callback != AjaxPro.noOperation;
 5        var json = AjaxPro.toJSON(data) + "/r/n";
 6
 7        if(AjaxPro.cryptProvider != null)
 8            json = AjaxPro.cryptProvider.encrypt(json);
 9
10        this.callback = callback;
11
12        if(async) {
13            this.xmlHttp.onreadystatechange = this.doStateChange.bind(this);
14            if(typeof this.onLoading == "function"this.onLoading(true);
15        }

16            
17        this.xmlHttp.open("POST"this.url, async);
18        this.xmlHttp.setRequestHeader("Content-Type""application/x-www-form-urlencoded");
19        this.xmlHttp.setRequestHeader("Content-Length", json.length);
20        this.xmlHttp.setRequestHeader("Ajax-method", method);
21        
22        if(AjaxPro.token != null && AjaxPro.token.length > 0)
23            this.xmlHttp.setRequestHeader("Ajax-token", AjaxPro.token);
24
25        if(MS.Browser.isIE)
26            this.xmlHttp.setRequestHeader("Accept-Encoding""gzip, deflate");
27        else
28            this.xmlHttp.setRequestHeader("Connection""close");    // Mozilla Bug #246651
29
30        if(this.onTimeout != null && typeof this.onTimeout == "function")
31            this.timeoutTimer = setTimeout(this.timeout.bind(this), this.timeoutPeriod);
32
33        this.xmlHttp.send(json);
34        
35        json = null;
36        data = null;
37        delete json;
38        delete data;
39        
40        if(!async) {
41            return this.createResponse();
42        }

43        
44        return true;    
45    }

46}
);
47  七、this.xmlHttp 从何而来?

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

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

4

NET技术AjaxPro 内部机制探讨,转载需保留来源!

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。