让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代码):

 

ContractedBlock.gif ExpandedBlockStart.gif 代码
 
      
<%
// 下面设置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代码:

 

ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
<! 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 >

 

 

 

 

    运行效果图: 

    2010060117302946.jpg2010060117280795.jpg

 

缺点:

     看到这里或许你已经蠢蠢欲动,想自己动手试试了。但是注意上面的方法虽好,但也有个缺点,就是浏览器的支持问题。目前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.cnblogs.com/BearsTaR/
[声明]:本博所有文章版权归作者所有(除特殊说明以外),转载请注明出处.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值