AJAX 数据传输进度条设计与实现
2015-10-15 17:57
288 查看
AJAX 无疑是主流的客户端和服务器端通信的方式,AJAX 通信方式当然有很多优点,但是缺点也一定程度上是由优点造成的,因为AJAX 通信过程中,页面不会全局刷新,这在传输的数据量比较小且网速比较好的时候,是没有什么问题的,但是当数据量比较大的时候,页面就会长时间没有任何反应,可能让用户误以为请求失败,所以在数据传输没有完成的等待时间内,我们以一个进度条或者缓冲环给用户以正在通信的可视化效果,这样用户体验就会大大提升。
那么怎么实现呢?我们首先来看看 AJAX 的通信原理。
loadstart,当接收到服务器相应的第一个字节时触发;
progress,在接收数据期间不断的触发;
error,当请求发生错误时触发;
abort,调用 abort 函数时触发;
load,接收数据完成时触发;
loadend,整个通信过程完成后触发。
这些事件各个浏览器的支持程度如何呢?我们可以看一幅图:
目前,PC 浏览器只有 IE 不支持这些事件的所有实现,但是并不影响我们要使用的事件,Opera Mini 是针对手机的 Opera 浏览器,用的并不多。根据现在的支持程度,我们可以使用 Progress Events 实现一些应用,比如本文要实现的进度条。
本文要实现的“进度条”直接用到的事件是
target,对应的 XHR 对象;
lengthComputable,表示进度信息是否可用的布尔值;
loaded,已经接收的字节数;
total,响应数据的预期总字节数,根据 Content-Length 响应头部确定。
这样我们通过监听 progress 事件,查看 position 的值与 total 的比值,就能确定接收数据的百分比,通过进度条显示,即可完成预期效果。
1、例子兼容 IE 9+
2、使用了JQuery 和 Bootstrap 进度条
控制进度条的已完成进度是
注意,progress 事件要在 open 之前绑定,如果
注意到
最后,我们运行页面,可以看到:
当然,表示进度,并不一定要使用条形,我们可以换成 环形等形状,大致的原理都是一样的,将后台返回的进度动态改变前台的缓冲进度。
当我们必须要在不支持 progress 事件的浏览器中实现类似功能时,我们可以利用所有浏览器都支持 AJAX 这个特性,请求开始和请求成功都有明确的时间点,我们退而求其次,不使用有刻度的进度条,而使用一个缓冲环,在请求完成之前,一直处于缓冲状态。
这样,至此为止,我们考虑了支持所有浏览器的 AJAX 请求进度显示,和各个形状的进度条。
OK,就写到这里吧!有什么问题可以博客下留言评论。
那么怎么实现呢?我们首先来看看 AJAX 的通信原理。
一、 AJAX 通信原理
W3C 一个工作草案规定了 Progress Event,定义了与客户端和服务器通信有关的事件。这些事件最初只是针对 AJAX 操作,现在其他的 API 也开始借鉴。主要进度事件有六个:loadstart,当接收到服务器相应的第一个字节时触发;
progress,在接收数据期间不断的触发;
error,当请求发生错误时触发;
abort,调用 abort 函数时触发;
load,接收数据完成时触发;
loadend,整个通信过程完成后触发。
这些事件各个浏览器的支持程度如何呢?我们可以看一幅图:
目前,PC 浏览器只有 IE 不支持这些事件的所有实现,但是并不影响我们要使用的事件,Opera Mini 是针对手机的 Opera 浏览器,用的并不多。根据现在的支持程度,我们可以使用 Progress Events 实现一些应用,比如本文要实现的进度条。
本文要实现的“进度条”直接用到的事件是
progress事件,各个浏览器都支持,是由 Mozilla 引入的革新。该事件触发时,事件处理程序会接收一个事件对象 event,该事件对象包含四个我们要用到的属性:
target,对应的 XHR 对象;
lengthComputable,表示进度信息是否可用的布尔值;
loaded,已经接收的字节数;
total,响应数据的预期总字节数,根据 Content-Length 响应头部确定。
这样我们通过监听 progress 事件,查看 position 的值与 total 的比值,就能确定接收数据的百分比,通过进度条显示,即可完成预期效果。
二、 实现
注:1、例子兼容 IE 9+
2、使用了JQuery 和 Bootstrap 进度条
2.1 HTML 页面
首先我们编辑 HTML 页面,页面中包含一个 bootstrap 进度条,同时包含一个按钮,用以触发请求数据,并同时修改进度条进度。HTML 页面主要部分实现如下:<div class="progress"> <div id="pros" class="progress-bar progress-bar-striped active" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width: 0%;"> </div> </div> <button id="trigger_ajax" type="button" >请求数据</button>
控制进度条的已完成进度是
id="pros"的 DIV 的 width 属性,在进度条上显示的进度文字,是 DIV 内含的文字
text,我们通过改变这两个属性,就可以实现进度的动态变化。
2.2 AJAX 请求
我们给按钮绑定点击事件,用来请求服务器端的数据:var trigger = document.getElementById("trigger_ajax"); trigger.onclick = function(){ var xhr = new XMLHttpRequest(); xhr.onprogress = function(event){ if(event.lengthComputable){ var loaded = parseInt(event.loaded/event.total*100)+"%"; $('#pros').width(loaded); $('#pros').text(loaded); } } xhr.open("post", "for_test.php", true); xhr.send(null); }
注意,progress 事件要在 open 之前绑定,如果
event.lengthComputable返回结果为 ture,那么就根据服务器的返回数据状态改变进度条的状态:
if(event.lengthComputable){ var loaded = parseInt(event.loaded/event.total*100)+"%"; $('#pros').width(loaded); $('#pros').text(loaded); }
2.3 服务器端返回数据
最后我们要写出服务器端的代码,我使用的 PHP ,有一点需要注意,服务器端的代码过程要“返回结果比较大,传输需要一段时间”,我们写一个比较大的循环,组成一个非常长的字符串,然后返回这个字符串:<?php $results=""; for($i=1; $i<=900000; $i++){ $results.='"'.$i.'"'; } $len = strlen($results); header("Content-Length: $len"); echo $results; ?>
注意到
header("Content-Length: $len");,写出 http 头时候,附加 “Content-Length”,这样 JS 端的 progress 事件的 event.lengthComputable 值才会为
true, event.total 才会在数据传输完毕之前取得值,否则 event.lengthComputable 值会返回
false, event.total 在数据完成之前值都是
0。
最后,我们运行页面,可以看到:
三、 总结
我们可以把这个进度条应用在请求数据量比较大的情境中,在传输数据的过程中给用户以直观的视觉感知,这样会提升用户的体验。或者应用在网络较差的情况下,请求时间可能会较长,当用户触发网络请求后,弹出一个包含进度条的弹出框,当请求完毕后,弹出框自动消失。当然,表示进度,并不一定要使用条形,我们可以换成 环形等形状,大致的原理都是一样的,将后台返回的进度动态改变前台的缓冲进度。
当我们必须要在不支持 progress 事件的浏览器中实现类似功能时,我们可以利用所有浏览器都支持 AJAX 这个特性,请求开始和请求成功都有明确的时间点,我们退而求其次,不使用有刻度的进度条,而使用一个缓冲环,在请求完成之前,一直处于缓冲状态。
这样,至此为止,我们考虑了支持所有浏览器的 AJAX 请求进度显示,和各个形状的进度条。
OK,就写到这里吧!有什么问题可以博客下留言评论。
相关文章推荐
- OpenJWeb在Eclipse EE下的配置要点
- webrtc音频引擎之CNG模块介绍
- sphinx 文档,思路,方法 整理
- SDUST-OJ-1681 Problem 求集合的交并补集(不用STL,手写单链表实现)
- 获取设备型号
- QT5入门之12 - 禁止改变窗体大小
- commitallowingstateloss 和commit的区别
- HTML+CSS实现loading
- 关于kali Linux工具打开提示SyntaxError: invalid syntax
- C. Captain Marmot (Codeforces Round #271)
- java在本地访问阿里云OCS
- Android activity的startActivityForResult和onActivityResult与启动模式的关系
- 性能测试解释
- 学习笔记-音频编解码
- ssm框架整合
- 内存分配器
- swift 初级 第一个程序 HollowWorld
- Java中给数字补位
- 如何在安卓app中使用FontAwesome图标
- Office在线预览