|
應(yīng)當(dāng)承認(rèn)我這人實(shí)在算不上弄潮兒,Ajax 早已流行得一塌糊涂,我卻始終沒有來研究一下這個(gè)東東。上次做網(wǎng)站的時(shí)候,BOSS 就跟我講過,可以參考一下 Ajax 的技術(shù),我嘴上答應(yīng),心里卻不是十分的在乎。究其原因,一來是我這人比較固步自封,二來起初確實(shí)也沒太相信 Ajax 真有 BOSS 說的那么神奇。
轉(zhuǎn)變是從昨天天始的,這一周在公司主要精力都是在用 C++ 寫 framework,不得不承認(rèn)它比較辛苦,細(xì)枝末節(jié)之處非常之煩,昨天下午呆著呆著就不想干活了,就開始四處游蕩,正好看到我們自己也有項(xiàng)目已經(jīng)成功應(yīng)用了 Ajax,于是也就想看一看,無奈那幫家伙的開發(fā)文檔是出奇的少,只好在網(wǎng)上找找資料,自己研究研究吧。
作為一個(gè)技術(shù)人員,我看到一項(xiàng)新技術(shù),總是喜歡琢磨琢磨它內(nèi)部是如何實(shí)現(xiàn)的。在對 Ajax 有了初步認(rèn)識以后,自然想看看其內(nèi)部機(jī)制,但是令我失望的是,至少介紹 Ajax 內(nèi)部實(shí)現(xiàn)的文章少之又少,好容易找到一篇,卻也只是簡單列了列一些 Javascript 代碼,并且沒什么解釋,頗為郁悶。想想求人不如求己,況且自己研究的或許印象更深一些。于是找到了一個(gè) AjaxPro,下來琢磨琢磨,只是對于 JavaScript 我實(shí)在知之甚少,不明白之處依然很多,不過還是想寫出來,拋磚引玉,望高人們不吝指教。
一、使用的例子
本文使用的例子很簡單,一個(gè)文本框,在其中敲入文字之后,下方就顯示該文字并加上一個(gè)“(Hello from server)”。源碼如下(有刪節(jié)):
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
15script>
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
47script> 二、Ajax ClientScript 的執(zhí)行總體流程
好,有了源頁面代碼,又有了兩個(gè) ClientScript 文件,我們就可以分析客戶端的執(zhí)行流程了。以下是我畫的一張簡單的流程圖:
我們一個(gè)一個(gè)地來分析。
三、HTML頁面做了什么?
第一步,當(dāng)我們在 TextBox 里輸入字符后,將會觸發(fā) onkeyup 事件。它要執(zhí)行 doTest1 方法。見頁面代碼里的第22行。
第二步,doTest1 方法使用 setTimeout 函數(shù),設(shè)定了 100 毫秒后,執(zhí)行 doTest1_next 方法。見頁面代碼里的第34行。
第三步,doTest1_next 方法調(diào)用了 ASP.KeyPressDemo.EchoInput 方法,它帶有兩個(gè)參數(shù),第一個(gè)是我們在文本框中輸入的值,當(dāng)然是個(gè)字符串類型的了;第二個(gè)則是一個(gè) callback 函數(shù),請留心這個(gè)函數(shù),它將于整個(gè)流程的最后執(zhí)行。
好,我們知道頁面的客戶端無外乎就是 HTML 和 JavaScript,雖然 ASP.KeyPressDemo.EchoInput 方法酷似頁面里我們自己用 C# 寫的函數(shù),但可以肯定的是它絕對是用 JavaScript 實(shí)現(xiàn)的。在哪兒呢?嗯,在我們從 Temporary InterNET Files 目錄下找到的 ASP.KeyPressDemo,App_Web_vxhzzzxr.ashx 里。
四、ASP.KeyPressDemo,App_Web_vxhzzzxr.ashx 的實(shí)現(xiàn)
這個(gè)文件很小,以下是它的全部源碼:
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 函數(shù)
Invoke 函數(shù)是核心所在,前面我畫的流程圖中已經(jīng)簡單地描述了它的主要流程。不過這個(gè)函數(shù)太重要了,這里還是列出它的全部源碼:
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 函數(shù)吧(有刪節(jié)):
1


2

3

4

NET技術(shù):AjaxPro 內(nèi)部機(jī)制探討,轉(zhuǎn)載需保留來源!
鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請第一時(shí)間聯(lián)系我們修改或刪除,多謝。