<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      ajaxpro 原理

      應(yīng)當(dāng)承認(rèn)我這人實(shí)在算不上弄潮兒,Ajax 早已流行得一塌糊涂,我卻始終沒有來研究一下這個東東。上次做網(wǎng)站的時候,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)上找找資料,自己研究研究吧。

        作為一個技術(shù)人員,我看到一項(xiàng)新技術(shù),總是喜歡琢磨琢磨它內(nèi)部是如何實(shí)現(xiàn)的。在對 Ajax 有了初步認(rèn)識以后,自然想看看其內(nèi)部機(jī)制,但是令我失望的是,至少介紹 Ajax 內(nèi)部實(shí)現(xiàn)的文章少之又少,好容易找到一篇,卻也只是簡單列了列一些 javascript 代碼,并且沒什么解釋,頗為郁悶。想想求人不如求己,況且自己研究的或許印象更深一些。于是找到了一個 AjaxPro,下來琢磨琢磨,只是對于 JavaScript 我實(shí)在知之甚少,不明白之處依然很多,不過還是想寫出來,拋磚引玉,望高人們不吝指教。

        一、使用的例子

        本文使用的例子很簡單,一個文本框,在其中敲入文字之后,下方就顯示該文字并加上一個“(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
      15
      </script>
      16
      17<form id="Form1" method="post" runat="server"></form>
      18
      19<div class="content">
      20<h1>KeyPressDemo Examples</h1>
      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>
      24</div>
      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>

        選用這個例子,是因?yàn)樗容^簡單,沒有相關(guān)的 C# 文件。首先看看第17行,咦?怎么這個 form 里啥都沒有?既然什么都沒有?刪掉它行不行?不行,絕對不行!看看網(wǎng)頁打開后,這一行被擴(kuò)展成了什么?

      1<form name="Form1" method="post" action="keypress.aspx" id="Form1">
      2<div>
      3<script type="text/javascript" src="/ajaxdemo/ajaxpro/core.ashx"></script>
      4<script type="text/javascript" src="/ajaxdemo/ajaxpro/ASP.KeyPressDemo,App_Web_vxhzzzxr.ashx"></script>
      5</form>
      6

        請注意這里鏈入的兩個 javascript 文件,它們是 Ajax 得以運(yùn)行的基礎(chǔ)!刪掉 form 那一行,它們就不會出現(xiàn),自然不行了。這兩行是如何產(chǎn)生的?那就是頁面代碼的第4至7行的 PageLoad 函數(shù)的功勞了。

        好,那這兩個 javascript 文件我們能看到不?看上去它們是服務(wù)端的,并且事實(shí)上是服務(wù)端動態(tài)生成的。不過稍有些了解瀏覽器工作原理的人就會知道,到 Local Settings 下的 Temporary Internet Files 目錄下去找,肯定是有的,因?yàn)闉g覽器下載頁面的時候會把與頁面相關(guān)的文件都下過來。

        二、Ajax ClientScript 的執(zhí)行總體流程

        好,有了源頁面代碼,又有了兩個 ClientScript 文件,我們就可以分析客戶端的執(zhí)行流程了。以下是我畫的一張簡單的流程圖:



        我們一個一個地來分析。

        三、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 方法,它帶有兩個參數(shù),第一個是我們在文本框中輸入的值,當(dāng)然是個字符串類型的了;第二個則是一個 callback 函數(shù),請留心這個函數(shù),它將于整個流程的最后執(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)

        這個文件很小,以下是它的全部源碼:

       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

        啊哈,這下我們知道了,ASP.KeyPressDemo 其實(shí)是在這里用 JavaScript 定義的 ASP.KeyPressDemo_class 類的實(shí)例,EchoInput 則是它的一個方法。注意一下每3行,我們看到這個類是從 AjaxPro.Request 類繼承的。什么什么?繼承?有沒有搞錯?JavaScript 什么時候開始面向?qū)ο罅硕皇腔趯ο罅耍肯葦[下這個疑問,我們繼續(xù)往下看。

        EchoInput 方法的實(shí)現(xiàn)很簡單,就是調(diào)用了一個 Invoke 方法。嗯,這個方法想必是從 AjaxPro.Request 類“繼承”下來的。那它定義在哪兒?是了,還有一個 core.ashx 呢,它才是真正客戶端實(shí)現(xiàn) Ajax 技術(shù)的主角!這個文件太大,我們還是依照函數(shù)調(diào)用順序慢慢來拆解罷。

        五、Invoke 函數(shù)

        Invoke 函數(shù)是核心所在,前面我畫的流程圖中已經(jīng)簡單地描述了它的主要流程。不過這個函數(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


        嗯,相當(dāng)復(fù)雜啊。我們慢慢地看。

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

        第4行的 async,字面上理解就是指異步,這一行什么意思?嗯,如果傳進(jìn)來的 callback 類型是函數(shù),并且不是無操作,那就認(rèn)為是異步的。

        第5行的 json,它可是相當(dāng)重要啊。這里調(diào)用了 AjaxPro.toJSON 方法把傳進(jìn)來的數(shù)據(jù)進(jìn)行了某種編碼,本例中這個數(shù)據(jù)當(dāng)然就是從 doTest1_next 一路傳進(jìn)來的 TextBox 里我們輸入的字符串值了,這個函數(shù)的實(shí)現(xiàn),本文也不再列出,可以參見 core.ashx 文件。

        接下來第7到8行,如果提供了加密,那么就對 json 進(jìn)行加密。這個好理解。

        第12到15行,如果是異步的,那么這里將 doStateChange 函數(shù)綁定到 onreadystatechange 事件上去。嗯,這里的綁定其實(shí)也是在 core.ashx 文件里聲明的一個方法,本文不再闡述它的實(shí)現(xiàn)了,大家有興趣,可以自己去看。綁定完成后,當(dāng)服務(wù)端完成操作后,doStateChange 函數(shù)會被調(diào)用,這時可以進(jìn)行更改頁面的工作。此外,這里還檢測了一下 onLoading 事件。

        第17行到第33行可謂核心代碼,我們知道 Ajax 就是使用的 XMLHttpRequest 來完成無刷新頁面的。這里我們可看到 this.xmlHttp 被用來進(jìn)行了請求封裝。其中值得我們注意的,Content-Length 使用的 json.length,Ajax-method 則使用的就是傳進(jìn)來的 AjaxMethod 方法名稱,本例中為 EchoInput。第30、31行設(shè)置了超時處理,當(dāng)然了,頁面不能死等嘛。第33行則將 json 發(fā)送到服務(wù)端。

        接下來的第41行,我們看到如果不是異步操作的話,此處將直接調(diào)用 createResponse 函數(shù)獲得響應(yīng)。那如果是異步操作呢?記得我們設(shè)置了 doStateChange 吧?異步的返回處理就是它的事了。createResponse 函數(shù)后面再介紹。

        六、解釋“繼承”

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

      1Object.extend = function(destination, source) {
      2    for(property in source) {
      3        destination[property] = source[property];
      4    }

      5    return destination;
      6}

      7

        哈哈,所謂的“繼承”,其實(shí)只是個屬性拷貝而已。

        七、this.xmlHttp 從何而來?

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

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

      4

        是了,xmlHttp 只是 XMLHttpRequest 的一個實(shí)例。那么 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

        哦,原來是在這里真正創(chuàng)建的。說到底還是一個 ActiveXObject 啊。關(guān)于這個本文也不再多提。不過代碼中還需要注意的一點(diǎn)是,
      如果把第19行列出的一大堆clsids 都處理過了還沒有得到對象怎么辦?注意到第26行 new 了一個 IFrameXmlHttp。

        IFrameHttp 是在 core.ashx 中定義的,它基本上完全模擬了 ActiveXObject 對象的功能。想研究研究的,自己看源碼吧。篇幅所限,這里不多講啦。

        八、doStateChange 函數(shù)

        嗯,前面已經(jīng)提過,異步的話 doStateChange 函數(shù)將會在服務(wù)端返回后執(zhí)行,看看它的源碼呢:

       1doStateChange: function() {
       2    if(this.onStateChanged != null && typeof this.onStateChanged == "function")
       3        trythis.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,那么清除掉超時處理函數(shù),處理 onLoading 事件,最后使用 callback 調(diào)用 createResponse 函數(shù)。還記得如果不是異步的話,createResponse 將會直接調(diào)用而不是通過 doStateChange 吧。

        九、createResponse 函數(shù)

       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        trythis.onError(r.error); }catch(e){}
      15
      16    responseText = null;
      17
      18    return r;
      19}

        如果前面的 json 也就是 Request 是加過密的,這里就需要對 responseText 進(jìn)行解密。完了之后得到 r.value,r 將會被返回并提供給 callback 函數(shù)。本例中將最終傳回 doTest1_callback,r 被傳入它的 res 參數(shù)。最后更新文本框下的字符串,整個 Ajax ClientScript 的流程就差不多是完成了。

        十、簡單總結(jié)一下

        呼,長出一口氣。總算可以告一段落了,AjaxPro 服務(wù)端的拆解過段時間再說吧。

        在分析 ClientScript 端的時候真是大有感觸,JavaScript 其實(shí)遠(yuǎn)比人們想象的強(qiáng)大和管用。其實(shí)我同大多數(shù)人一樣,起初也對它很不感冒,但是之前曾有兩件事讓我改變了觀念。其一是閱讀了黃忠成的《深入剖析 ASP.NET 組件設(shè)計(jì)》,才發(fā)現(xiàn)原來許多強(qiáng)大炫目的 ASP.NET 的控件,其實(shí)都是用的 JavaScript 實(shí)現(xiàn)。其二是在研究國外某文檔瀏覽器實(shí)現(xiàn)的時候,發(fā)現(xiàn)人家使用 JavaScript 在 IE 下相當(dāng)完美地實(shí)現(xiàn)了強(qiáng)大靈活有如桌面程序的界面和功能,真是吃驚不小。當(dāng)時就發(fā)現(xiàn)了自己對 JavaScript 的了解實(shí)在是嚴(yán)重汗顏,慚愧無地。無奈平時沒有多少時間去學(xué)習(xí)提高自己,只能偶爾抽抽空余時間了解了解,充充電吧。

        相信 JavaScript 之類的腳本必將在未來的 Web 應(yīng)用中大展身手。

      posted @ 2007-02-16 16:42  Leepy  閱讀(1426)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 2020中文字字幕在线不卡| 青青草原国产精品啪啪视频| 4399理论片午午伦夜理片| 日韩有码国产精品一区| 国产av午夜精品福利| 潮喷失禁大喷水av无码| 国产精品无码无在线观看| 亚洲国产成人久久综合同性 | 99精品国产在热久久婷婷| av无码精品一区二区乱子| 午夜精品福利亚洲国产| 亚洲伊人久久综合成人| 成人国产乱对白在线观看| 人人人爽人人爽人人av| 亚洲综合色婷婷中文字幕| 国产真人做受视频在线观看| 极品白嫩少妇无套内谢| 国产精品午夜福利91| 国产精品亚洲а∨天堂2021 | 亚洲精品在线二区三区| 国产乱码一区二区三区免费| 教育| 无遮挡高潮国产免费观看| 男女激情一区二区三区| 99RE8这里有精品热视频| 国产亚洲精品第一综合麻豆 | 日本韩国日韩少妇熟女少妇| 任你躁国产自任一区二区三区| 亚洲国产良家在线观看| 在线播放国产精品三级网| 亚洲精品久久久久午夜福禁果tⅴ| 国产免费播放一区二区三区| 亚洲一区二区日韩综合久久| 国产精品久久一区二区三区| 熟女人妻精品一区二区视频| 免费a级毛片无码av| 成人永久免费A∨一级在线播放| 麻豆精品久久久久久久99蜜桃| 中文字幕日韩一区二区不卡| 亚洲天堂成人网在线观看| аⅴ天堂国产最新版在线中文 |