热门:网页模板.net视频教程JQueryMVCjsonExtJs源码示例三级联动JQuery菜单
您现在的位置:.Net中文社区>> AJAX编程>>正文内容

让ajax更加友好,实时显示后台处理进度。

发布时间:2010年06月25日点击数: 佚名

 ajax应用越来越多,大部分ajax处理都是在前台显示1个"loading...",然后把数据提交给服务器进行处理,处理完毕后显示"处理完毕"。我们能否让ajax更加友好点,实时显示服务器处理的进度了?这在一些长时间的请求中尤其重要,比如上传文件、发送邮件、批量处理数据。答案当然是可以的,不然就不会写这个了,对吧,^_^。


存在的问题:【在线示例地址
要解决实现上面的功能,需要解决下面几个问题:
1. 服务器如何在处理一部分数据后传递部分response到浏览器。
2、浏览器如何能处理服务器传递过来部分数据,并保持http连接直到处理完全完毕。

要解决第1个问题,使用flush让response分块进行呈现就可以了,具体请参考我另一遍随笔"flush让页面分块,逐步呈现";
第2个问题,则需要用到XMLHttpRequest的readyState状态,w3c对 readyState 定义如下几个值:   

  1. UNSENT = 0;     // 没有发送请求 
  2. OPENED = 1;    // 已经打开http连接 
  3. HEADERS_RECEIVED = 2; // 接收到response header 
  4. LOADING = 3;          // 真正接收response body    
  5. DONE = 4;             // 请求接收完毕 

相信状态4大家是天天在用,而我们这里需要用到就是状态3。

实例:
废话少说,代码实例比什么文字解释都管用。我们这里假设服务器的1个处理需要6秒种,每秒种处理1条记录,总共处理6条记录,我们需要服务器每处理完1条数据,客户端则显示处理进度(包括文字和进度条)。

服务器端代码(下面JSP代码): 

  1. <% 
  2.  // 下面设置Content-Type:application/x-javascript 是为了适应Webkit的浏览器(chrome,safari) 
  3. response.setHeader("Content-Type","application/x-javascript"); 
  4. int count = 6;  //  处理6条数据 
  5. for(int i=0;i<count;i++){ 
  6.     // 处理完毕一条,输出结果到客户端 
  7.     out.println(i+1); 
  8.     out.flush(); 
  9.     // 这里假设每条数据处理时间为1秒 
  10.     Thread.currentThread().sleep(1000); 
  11. %> 

html代码:

  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
  2. <html xmlns="http://www.w3.org/1999/xhtml"> 
  3. <head> 
  4.     <style> 
  5.         #divProgress{width:300px;height:24px;position:relative;} 
  6.         #divProgress div{position:absolute;left:0;top:0;height:24px;} 
  7.         #progressBg{background-color:#B9F8F9;z-index:10;} 
  8.         #progressText{z-index:15;text-align:center;width:100%;} 
  9.     </style>     
  10. </head> 
  11. <body> 
  12.      <div id="divProgress"> 
  13.          <div id="progressBg"></div> 
  14.          <div id="progressText"></div> 
  15.      </div> 
  16.      <br /> 
  17.      <button onclick="send()">提交数据</button> 
  18.      <script> 
  19.         var t = document.getElementById("progressText"); 
  20.         var bg = document.getElementById("progressBg"); 
  21.         function send(){ 
  22.             t.innerHTML = "loading..."
  23.             bg.style.width = "0px"
  24.              
  25.             var xhr = new window.XMLHttpRequest(); 
  26.             if(!window.XMLHttpRequest){ 
  27.                     try { 
  28.                         xhr = new window.ActiveXObject("Microsoft.XMLHTTP"); 
  29.                     } catch(e) {} 
  30.             } 
  31.             xhr.open("post","http://localhost:801/ChunkTest/chunk.jsp?count=6"); 
  32.             var oldSize=0
  33.             xhr.onreadystatechange = function(){ 
  34.                 if(xhr.readyState > 2){                  
  35.                   var tmpText = xhr.responseText.substring(oldSize);  
  36.                   oldSize = xhr.responseText.length; 
  37.                   if(tmpText.length > 0 ){ 
  38.                     // 设置文本 
  39.                     t.innerHTML = tmpText + "/6"; 
  40.                     // 设置进度条 
  41.                     var width = parseInt(tmpText)/6*300; 
  42.                     bg.style.width = width+"px"; 
  43.                     } 
  44.                 } 
  45.                 if(xhr.readyState == 4){  
  46.                     // 请求执行完毕 
  47.                     t.innerHTML = "执行完毕"
  48.                     bg.style.width = "300px"
  49.                 } 
  50.             } 
  51.             xhr.send(null); 
  52.       } 
  53.     </script> 
  54. </body> 
  55. </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

本站热点业务

更多模板/案例展示

关于我们 | 联系我们 | 团队日志 | 网站地图 | 网站合作