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

1
2
3
4
5
6
7
8
9
10
11
12
<%
  // 下面设置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代码:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<! 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.jpg 2010060117280795.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/archive/2010/06/02/ajax_better_Experience.html  ,如需转载请自行联系原作者



相关文章
|
4月前
|
存储 移动开发 JavaScript
【原生】sd.js帮助您简化繁重的获取数据、存储数据(CRUD)骚操作(吐槽~在安卓9.0以下或者IOS10.X以下手机端H5页面不支持,在这两种情况下的系统只能使用ajax或者原生js请求后台数据)
【原生】sd.js帮助您简化繁重的获取数据、存储数据(CRUD)骚操作(吐槽~在安卓9.0以下或者IOS10.X以下手机端H5页面不支持,在这两种情况下的系统只能使用ajax或者原生js请求后台数据)
|
4月前
|
前端开发 JavaScript
解决Ajax发送DELETE请求时后台无法接收到参数的问题(Restful风格)
解决Ajax发送DELETE请求时后台无法接收到参数的问题(Restful风格)
60 0
|
5月前
|
前端开发
Ajax提交请求后台返回一个完整的html页面
Ajax提交请求后台返回一个完整的html页面
|
8月前
|
前端开发
如何对ajax请求的后台数据添加到swiper轮播图并展示到页面
如何对ajax请求的后台数据添加到swiper轮播图并展示到页面
99 0
|
8月前
|
前端开发
如何用ajax请求后台数据的两种全网最实用且详细的写法
如何用ajax请求后台数据的两种全网最实用且详细的写法
86 0
|
9月前
|
前端开发
解决.NET Core Ajax请求后台传送参数过大请求失败问题
解决.NET Core Ajax请求后台传送参数过大请求失败问题
|
9月前
|
前端开发 数据可视化 JavaScript
ajax刷新php后台实现定时任务的执行解决方案
ajax刷新php后台实现定时任务的执行解决方案
71 0
|
10月前
|
JSON 前端开发 Java
使用ajax往后台传输json数据SpringMVC的RequestBody自动转换 前端控制器报400错误
使用ajax往后台传输json数据SpringMVC的RequestBody自动转换 前端控制器报400错误
|
10月前
|
XML JSON 前端开发
Qt+QtWebApp开发笔记(五):http服务器html中使用json触发ajax与后台交互实现数据更新传递
前面完成了页面的跳转、登录,很多时候不刷新页面就想刷新局部数据,此时ajax就是此种技术,且是异步的。   本篇实现网页内部使用js调用ajax实现异步交互数据。   在js中使用 ajax是通过XMLHttpRequest来实现的。
|
11月前
|
JSON 前端开发 Java
【Java框架型项目从入门到装逼】第六节 - 用ajax请求后台数据
【Java框架型项目从入门到装逼】第六节 - 用ajax请求后台数据