<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 36, comments - 419, trackbacks - 0, articles - 0
      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

     

    ajax應用越來越多,大部分ajax處理都是在前臺顯示1個"loading...",然后把數據提交給服務器進行處理,處理完畢后顯示"處理完畢"。
    我們能否讓ajax更加友好點,實時顯示服務器處理的進度了?這在一些長時間的請求中尤其重要,比如上傳文件、發送郵件、批量處理數據。
    答案當然是可以的,不然就不會寫這個了,對吧,^_^。

          ajax應用越來越多,大部分ajax處理都是在前臺顯示1個"loading...",然后把數據提交給服務器進行處理,處理完畢后顯示"處理完畢"。我們能否讓ajax更加友好點,實時顯示服務器處理的進度了?這在一些長時間的請求中尤其重要,比如上傳文件、發送郵件、批量處理數據。答案當然是可以的,不然就不會寫這個了,對吧,^_^。

     

     

    存在的問題:    

       要解決實現上面的功能,需要解決下面幾個問題:

       1. 服務器如何在處理一部分數據后傳遞部分response到瀏覽器。

       2、瀏覽器如何能處理服務器傳遞過來部分數據,并保持http連接直到處理完全完畢。

     

       要解決第1個問題,使用flush讓response分塊進行呈現就可以了,具體請參考我另一遍隨筆"flush讓頁面分塊,逐步呈現";

       第2個問題,則需要用到XMLHttpRequest的readyState狀態,w3c對 readyState 定義如下幾個值:

      UNSENT = 0; // 沒有發送請求

      OPENED = 1;    // 已經打開http連接

      HEADERS_RECEIVED = 2; // 接收到response header

      LOADING = 3;          // 真正接收response body   

      DONE = 4;             // 請求接收完畢

       相信狀態4大家是天天在用,而我們這里需要用到就是狀態3。

     

     

    實例:  

         廢話少說,代碼實例比什么文字解釋都管用。我們這里假設服務器的1個處理需要6秒種,每秒種處理1條記錄,總共處理6條記錄,我們需要服務器每處理完1條數據,客戶端則顯示處理進度(包括文字和進度條)。

     

       服務器端代碼(下面JSP代碼):

        <%
        // 下面設置Content-Type:application/x-javascript 是為了適應Webkit的瀏覽器(chrome,safari)
          response.setHeader("Content-Type","application/x-javascript");
          
    int count = 6;    //    處理6條數據
          for(int i=0;i<count;i++){
              
    // 處理完畢一條,輸出結果到客戶端
              out.println(i+1);
              out.flush();
              
    // 這里假設每條數據處理時間為1秒
              Thread.currentThread().sleep(1000);
          }
       
    %>

     

        html代碼:

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        
    <style>
            #divProgress
    {width:300px;height:24px;position:relative;}
            #divProgress div
    {position:absolute;left:0;top:0;height:24px;}
            #progressBg
    {background-color:#B9F8F9;z-index:10;}
            #progressText
    {z-index:15;text-align:center;width:100%;}
        
    </style>    
    </head>
    <body>
         
    <div id="divProgress">
              
    <div id="progressBg"></div>
             
    <div id="progressText"></div>
         
    </div>
         
    <br />
         
    <button onclick="send()">提交數據</button>
         
    <script>
             
    var t = document.getElementById("progressText");
             
    var bg = document.getElementById("progressBg");
            
    function send(){
                t.innerHTML 
    = "loading";
                bg.style.width 
    = "0px";
                
                
    var xhr = new window.XMLHttpRequest();
                
    if(!window.XMLHttpRequest){
                        
    try {
                            xhr 
    = new window.ActiveXObject("Microsoft.XMLHTTP");
                        } 
    catch(e) {}
                }
                xhr.open(
    "post","http://localhost:801/ChunkTest/chunk.jsp?count=6");
                
    var oldSize=0;
                xhr.onreadystatechange 
    = function(){
                    
    if(xhr.readyState > 2){                 
                      
    var tmpText = xhr.responseText.substring(oldSize); 
                      oldSize 
    = xhr.responseText.length;
                      
    if(tmpText.length > 0 ){
                          
    // 設置文本
                          t.innerHTML = tmpText + "/6";
                          
    // 設置進度條
                          var width = parseInt(tmpText)/6*300;
                          bg.style.width 
    = width+"px";
                        }
                    }
                    
    if(xhr.readyState == 4){ 
                        
    // 請求執行完畢
                        t.innerHTML = "執行完畢";
                        bg.style.width 
    = "300px";
                    }
                }
                xhr.send(
    null);
          }
        
    </script>
    </body>
    </html>

     

        運行效果圖: 

        

     

    缺點:

         看到這里或許你已經蠢蠢欲動,想自己動手試試了。但是注意上面的方法雖好,但也有個缺點,就是瀏覽器的支持問題。目前IE所有版本的瀏覽器都不支持 xhr.readyState == 3狀態,IE瀏覽器不支持在response響應完畢前讀取responseText屬性。  具體可查看MSDN :  XMLHttpRequest Object 

         基于Webkit的瀏覽器支持的不是很好,需要設置Content-Type:application/x-javascript才行(經測試發現Content-Type:text/html在有些情況下正常,有些情況下又不正常,而用application/x-javascript都正常)。

         看到了缺點后是否又打擊了你的積極性了,其實針對IE,我們不需要做太多處理,IE不支持,就不會顯示進度,就變成跟傳統的ajax請求一樣,一直顯示1個loading直到請求完畢。我們只需要加1個簡單的判斷,判斷如果是ie則不執行xhr.readyState > 2中的代碼,如果不加判斷,IE下會報JS錯誤.

     

    DEMO:

       demo服務器不太好,而且在國外,隨時可能會點擊不了,而且有時候運行效果不是很好,大家知曉下,最好是把代碼copy到本地進行測試。

       請使用firefox或chrome查看demo,ie查看的效果跟一般的ajax沒什么不一樣。

       http://213.186.44.204:8080/ChunkTest/index.html 



    [作者]:BearRui(AK-47)
    [博客]: http://www.tkk7.com/bearrui/
    [聲明]:本博所有文章版權歸作者所有(除特殊說明以外),轉載請注明出處.
    英雄,別走啊,幫哥評論下:  

    精彩推薦 好文要頂 水平一般 看不懂 還需努力

    評論

    # re: 讓ajax更加友好,實時顯示后臺處理進度。  回復  更多評論   

    2010-06-02 12:32 by thebye85
    很不錯,謝謝分享

    # re: 讓ajax更加友好,實時顯示后臺處理進度。  回復  更多評論   

    2010-06-02 14:14 by 菠蘿大象
    為什么不用jQuery?jQuery的跨瀏覽器無疑是非常強大的。

    # re: 讓ajax更加友好,實時顯示后臺處理進度。  回復  更多評論   

    2010-06-02 14:17 by BearRui(AK-47)
    @thebye85
    謝謝支持

    # re: 讓ajax更加友好,實時顯示后臺處理進度。  回復  更多評論   

    2010-06-02 14:17 by BearRui(AK-47)
    @菠蘿大象
    jquery并沒有這樣的功能,jquery的ajax都是在readyState==4后才執行代碼

    # re: 讓ajax更加友好,實時顯示后臺處理進度。  回復  更多評論   

    2010-06-03 11:30 by noname
    感謝分享,這種方法適用于時間比較長而且可以預期處理時間的場景,如果時間很短就沒有必要。還是很有意思的

    # re: 讓ajax更加友好,實時顯示后臺處理進度。  回復  更多評論   

    2010-06-03 12:17 by BearRui(AK-47)
    @noname
    的確是這樣,并不是所有情況都適合使用這種方法。

    # re: 讓ajax更加友好,實時顯示后臺處理進度。  回復  更多評論   

    2010-06-04 10:20 by @beyondwcm
    ajax 還可以多次 out.flush();

    # re: 讓ajax更加友好,實時顯示后臺處理進度。  回復  更多評論   

    2010-06-04 13:10 by 稅國政
    可惜ie不支持啊

    # re: 讓ajax更加友好,實時顯示后臺處理進度。  回復  更多評論   

    2010-06-04 13:12 by BearRui(AK-47)
    呵呵,是有利有弊的

    # re: 讓ajax更加友好,實時顯示后臺處理進度。  回復  更多評論   

    2010-06-24 13:31 by pandora jewels
    值得一看,都是專業人士啊!

    # re: 讓ajax更加友好,實時顯示后臺處理進度。[未登錄]  回復  更多評論   

    2010-07-13 18:27 by 123
    很想知道你在 ie 中 是怎么處理 readstatus > 3 的??應該總有解決的
    辦法吧??

    # re: 讓ajax更加友好,實時顯示后臺處理進度。  回復  更多評論   

    2010-07-13 20:31 by BearRui(AK-47)
    @123

    IE 不支持readstatus ,如果IE要支持這種功能,就需要采用ajax輪詢服務器來實現。

    # re: 讓ajax更加友好,實時顯示后臺處理進度。[未登錄]  回復  更多評論   

    2010-07-14 16:20 by 123
    換句話說,你的這種實現方式很好,但是 ie 不支持,火狐是可以的,
    我測試過了。。那你能不能有其他的方式去實現這種 后臺處理進度,然后再前臺實現呢?? 比如用jquery,或者 其他的ajax 框架,來實現 這種 處理進度條呢??很期待你的杰作。。如果有,請發我的郵箱:ypcheng@yeah.net,
    謝謝!!!

    # re: 讓ajax更加友好,實時顯示后臺處理進度。  回復  更多評論   

    2010-07-15 13:15 by BearRui(AK-47)
    @123
    這種我也做過1個,是做數據導入的時候,使用ajax輪詢請求服務器上的導入進度,然后再前臺顯示,看找個時間寫出來。

    # re: 讓ajax更加友好,實時顯示后臺處理進度。  回復  更多評論   

    2012-05-21 13:19 by jidebingfeng
    好文章,頂一下!

    # re: 讓ajax更加友好,實時顯示后臺處理進度。  回復  更多評論   

    2012-05-21 13:19 by jidebingfeng
    文章很精彩,推薦一下!

    # re: 讓ajax更加友好,實時顯示后臺處理進度。  回復  更多評論   

    2014-07-17 17:20 by aliang
    jquery 1.5+應該可以實現吧

    var orgAjax = jQuery.ajaxSettings.xhr;
    jQuery.ajaxSettings.xhr = function () {
    var xhr = orgAjax();
    xhr.onreadystatechange = function() {
    alert(xhr.readyState)
    }
    return xhr;
    };
    主站蜘蛛池模板: 天天拍拍天天爽免费视频| 日韩精品极品视频在线观看免费| 精品熟女少妇AV免费观看| 亚洲无线一二三四区| 日韩亚洲国产高清免费视频| 亚洲码一区二区三区| 99久久99久久精品免费看蜜桃| 亚洲国产精品美女| 国产免费av片在线看| 亚洲AV无码AV男人的天堂不卡| 免费A级毛片无码A| 久久毛片免费看一区二区三区| 国产亚洲精品一品区99热| 中文字幕无码一区二区免费| 亚洲一区二区三区电影| 免费观看激色视频网站(性色) | a级精品九九九大片免费看| 国产av无码专区亚洲av果冻传媒| 99免费精品视频| 久久亚洲国产成人亚| 免费在线看v网址| 亚洲AV噜噜一区二区三区| 亚洲色偷偷综合亚洲AV伊人| 国产一级片免费看| 亚洲人成电影院在线观看| 国产乱子影视频上线免费观看| 精品免费久久久久国产一区 | 麻豆精品国产免费观看| 美女被暴羞羞免费视频| 亚洲精品美女久久久久99| 1000部禁片黄的免费看| 国产午夜亚洲精品不卡| 亚洲妇熟XXXX妇色黄| 女人18毛片a级毛片免费视频| 色哟哟国产精品免费观看 | 国产精品亚洲专区在线观看 | 亚洲国产精品嫩草影院久久| 日韩精品久久久久久免费| 亚洲av无码一区二区三区天堂| 亚洲女久久久噜噜噜熟女| 好先生在线观看免费播放|