浅析ProgressEvent接口及其应用:上传文件进度事件
一、ProgressEvent 介绍
ProgressEvent
接口是测量如 HTTP 请求(一个XMLHttpRequest
,或者一个 <img>
,<audio>
,<video>
,<style>
或 <link>
等底层资源的加载)等底层流程进度的事件。
1、构造方法:ProgressEvent()
(en-US):用给定的参数创建一个 ProgressEvent
事件。
2、属性:同时继承它的父元素 Event
的属性。
(1)ProgressEvent.lengthComputable
:只读。是一个 Boolean
(en-US) 标志,表示底层流程将需要完成的总工作量和已经完成的工作量是否可以计算。换句话说,它告诉我们进度是否可以被测量。
(2)ProgressEvent.loaded
(en-US) :只读。是一个 unsigned long long
类型数据,表示底层流程已经执行的工作总量。可以用这个属性和 ProgressEvent.total
计算工作完成比例。当使用 HTTP 下载资源,它只表示内容本身的部分,不包括首部和其它开销。
(3)ProgressEvent.total
(en-US) :只读。是一个 unsigned long long
类型数据,表示正在执行的底层流程的工作总量。当使用 HTTP 下载资源,它只表示内容本身的部分,不包括首部和其它开销。
3、方法:同时继承它的父元素 Event
的方法。
ProgressEvent.initProgressEvent()
(en-US),使用被弃用的 Document.createEvent("ProgressEvent")
方法,来初始化一个已经创建好的 ProgressEvent
。
4、下面的示例为一个新建的 XMLHTTPRequest
添加了一个 ProgressEvent
,并使用它来显示请求状态。
var progressBar = document.getElementById("p"),
client = new XMLHttpRequest()
client.open("GET", "magical-unicorns")
client.onprogress = function(pe) {
if(pe.lengthComputable) {
progressBar.max = pe.total
progressBar.value = pe.loaded
}
}
client.onloadend = function(pe) {
progressBar.value = pe.loaded
}
client.send()
二、进度事件(Progress Events)
Progress Events 定义了客户端与服务器通信有关的事件。这些事件最早其实只针对XHR操作,但目前也被其它API借鉴。有以下6个进度事件。
(1)loadstart:在接收到相应数据的第一个字节时触发。
(2)progress:在接收相应期间持续不断触发。
(3)error:在请求发生错误时触发。
(4)abort:在因为调用abort()方法而终止链接时触发。
(5)load:在接收到完整的相应数据时触发。
(6)loadend:在通信完成或者触发error、abort或load事件后触发。
每个请求都从触发 loadstart 事件开始,接下来是一或多个 progress 事件,然后触发 error、abort 或 load 事件中的一个,最后以触发 loadend 事件结束。
这些事件大都很直观,但其两个事件有一些细节需要注意。
1、load 事件
Firefox在实现XHR对象的某个版本时,曾致力于简化异步交互模型。最终,Firefox实现中引入了load事件,用以替代readystatechange事件。响应接收完毕后将触发Load事件,因此也就没有必要去检查readyState属性了。而onload事件处理程序会接收到一个event对象,其target属性就指向XHR对象实例,因而可以访问到XHR对象的所有方法和属性。然而,并非所有浏览器都为这个事件实现了适当的事件对象。结果,开发人员还是要被迫使用XHR对象变量。
2、progress 事件
progress 事件会在浏览器接收新数据期间周期性地触发。而 onprogress 事件处理程序会接收到一个 event 对象,其 target 属性是XHR对象,但包含着三个额外的属性:lengthComputable、loaded 和 total。
其中,lengthComputable是一个表示进度信息是否可用的布尔值,loaded表示已经接收的字节数,total 表示根据 Content-Length 响应头部确定的预期字节数。
有了这些信息,我们就可以为用户创建一个进度指示器了。下面展示了为用户创建进度指示器的一个示例。
var xhr = createXHR();
xhr.onload =function(){
if((xhr.status >=200&& xhr.status <300)|| xhr.status ==304){
alert(xhr.responseText);
}else{
alert("Request was unsuccessful: "+ xhr.status);
}
};
xhr.onprogress =function(event){
var divStatus = document.getElementById("status");
if(event.lengthComputable){
divStatus.innerHTML ="Recived"+event.loaded +" of "+event.total +" bytes";
}}
xhr.open("get","altevents.php",true);
xhr.send(null);
为确保正常执行,必须在调用 open() 方法之前添加 onprogress 事件处理程序。在前面的例子中,每次触发 progress 事件,都会以新的状态信息更新HTML元素的内容。如果响应头部中包含Content-Length字段,那么也可以利用此信息来计算从响应中已经接收到的数据的百分比。
// 当请求类型为post时需要监听xhr.upload。
// post 一般用来获取上传进度、get 用来获取下载进度
xhr.upload.onprogress =function(e){
if(e.lengthComputable){
console.log(e.loaded / e.total *100)
}
}