AjaxPro 內部機制探討-asp.net的結合,Ajax技術(2)

來源:互聯網
上載者:User
ajax|asp.net

五、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

  嗯,相當複雜啊。我們慢慢地看。

  AjaxPro.Request 類當然不是只有 Invoke 一個函數,這裡省去了其它函數。嗯,我們看到,AjaxPro.Request 也是從 AjaxPro.Base “繼承”下來的。

  第4行的 async,字面上理解就是指非同步,這一行什麼意思?嗯,如果傳進來的 callback 類型是函數,並且不是無操作,那就認為是非同步。

  第5行的 json,它可是相當重要啊。這裡調用了 AjaxPro.toJSON 方法把傳進來的資料進行了某種編碼,本例中這個資料當然就是從 doTest1_next 一路傳進來的 TextBox 裡我們輸入的字串值了,這個函數的實現,本文也不再列出,可以參見 core.ashx 檔案。

  接下來第7到8行,如果提供了加密,那麼就對 json 進行加密。這個好理解。

  第12到15行,如果是非同步,那麼這裡將 doStateChange 函數綁定到 onreadystatechange 事件上去。嗯,這裡的綁定其實也是在 core.ashx 檔案裡聲明的一個方法,本文不再闡述它的實現了,大家有興趣,可以自己去看。綁定完成後,當服務端完成操作後,doStateChange 函數會被調用,這時可以變更頁面的工作。此外,這裡還檢測了一下 onLoading 事件。

  第17行到第33行可謂核心代碼,我們知道 Ajax 就是使用的 XMLHttpRequest 來完成無重新整理頁面的。這裡我們可看到 this.XMLHttp 被用來進行了請求封裝。其中值得我們注意的,Content-Length 使用的 json.length,Ajax-method 則使用的就是傳進來的 AjaxMethod 方法名稱,本例中為 EchoInput。第30、31行設定了逾時處理,當然了,頁面不能死等嘛。第33行則將 json 發送到服務端。

  接下來的第41行,我們看到如果不是非同步作業的話,此處將直接調用 createResponse 函數獲得響應。那如果是非同步作業呢?記得我們設定了 doStateChange 吧?非同步返回處理就是它的事了。createResponse 函數後面再介紹。

  六、解釋“繼承”

  前面我們好幾次看到貌似繼承。當然它們都僅僅是貌似而已。看看以下 core.ashx 中的代碼就明白了:

1Object.extend = function(destination, source) {
2    for(property in source) {
3        destination[property] = source[property];
4    }
5    return destination;
6}
7
  哈哈,所謂的“繼承”,其實只是個屬性拷貝而已。

  七、this.XMLHttp 從何而來?

  前面我們看到了 this.XMLHttp 大顯神威。那麼它是哪兒來的?看看 AjaxPro.Request 類的 initialize 函數吧(有刪節):

1initialize: function(url) {
2    this.XMLHttp = new XMLHttpRequest();
3}
4
  是了,XMLHttp 只是 XMLHttpRequest 的一個執行個體。那麼 XMLHttpRequest 的定義呢?

 1var lastclsid = null;
 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 函數將會在服務端返回後執行,看看它的源碼呢:

 1doStateChange: 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 函數

 1createResponse: 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 應用程式中大展身手。

 



相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.