前面的话

  一般地,使用readystatechange事件探测HTTP请求的完成。XHR2规范草案定义了进度事件Progress Events规范,XMLHttpRequest对象在请求的不同阶段触发不同类型的事件,所以它不再需要检査readyState属性。这个草案定义了与客户端服务器通信有关的事件。这些事件最早其实只针对XHR操作,但目前也被其他API(如File API)借鉴。本文将详细介绍进度事件

基础

  有以下6个进度事件

  loadstart:在接收到响应数据的第一个字节时触发

  progress:在接收响应期间持续不断地触

  error:在请求发生错误时触发

  abort:在因为调用abort()方法而终止连接时触发

  load:在接收到完整的响应数据时触发

  loadend:在通信完成或者触发error、abort或load事件后触发

  timeout:超时发生时触发

  [注意]IE9-浏览器不支持以上事件(IE9浏览器仅支持load事件)

  每个请求都从触发loadstart事件开始,接下来,通常每隔50毫秒左右触发一次progress事件,然后触发load、error、abort或timeout事件中的一个,最后以触发loadend事件结束

  对于任何具体请求,浏览器将只会触发load、abort、timeout和error事件中的一个。XHR2规范草案指出一旦这些事件中的一个发生后,浏览器应该触发loadend事件

load

  响应接收完毕后将触发load事件,因此也就没有必要去检查readyState属性了。但一个完成的请求不一定是成功的请求,例如,load事件的处理程序应该检查XMLHttpRequest对象的status状态码来确定收到的是“200 OK”而不是“404 Not Found”的HTTP响应

<button id="btn">获取信息</button>
<div id="result"></div>
<script>
btn.onclick = function(){
//创建xhr对象
var xhr;
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}else{
xhr = new ActiveXObject('Microsoft.XMLHTTP');
}
//进度事件
xhr.onload = function(){
if(xhr.status == 200){
result.innerHTML += xhr.responseText;
}
}
//发送请求
xhr.open('get','message.xml',true);
xhr.send();
}
</script>

progress

  progress事件会在浏览器接收新数据期间周期性地触发。而onprogress事件处理程序会接收到一个event对象,其target属性是XHR对象,但包含着三个额外的属性:lengthComputable、loaded和total。其中,lengthComputable是一个表示进度信息是否可用的布尔值,loaded表示已经接收的字节数,total表示根据Content-Length响应头部确定的预期字节数。有了这些信息,就可以为用户创建一个进度指示器了

<button id="btn">获取信息</button>
<div id="result"></div>
<div id="music"></div>
<script>
btn.onclick = function(){
//创建xhr对象
var xhr;
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}else{
xhr = new ActiveXObject('Microsoft.XMLHTTP');
}
//进度事件
xhr.onprogress = function(e){
e = e || event;
if (e.lengthComputable){
result.innerHTML = "Received " + e.loaded + " of " + e.total + " bytes";
}
};
xhr.onload = function(e){
var data = xhr.response;
e = e || event;
if(xhr.status == 200){
var audio = document.createElement('audio');
audio.onload = function(){
URL.revokeObjectURL(audio.src);
}
audio.src = URL.createObjectURL(data);
console.log(audio);
audio.setAttribute('controls','');
if(!music.innerHTML){
music.appendChild(audio);
}
}
};
//发送请求
xhr.open('get','myocean.mp3',true);
xhr.responseType = 'blob';
xhr.send();
}
</script>

上传进度

  除了为监控HTTP响应的加载定义的这些有用的事件外,XHR2也给出了用于监控HTTP请求上传的事件。在实现这些特性的浏览器中,XMLHttpRequest对象将有upload属性。upload属性值是一个对象,它定义了addEventListener()方法和整个progress事件集合,比如onprogress和onload(但upload对象没有定义onreadystatechange属性,upload仅能触发新的事件类型)

  能仅仅像使用常见的progress事件处理程序一样使用upload事件处理程序。对于XMLHttpRequest对象,设置XHR.onprogress以监控响应的下载进度,并且设置XHR.upload.onprogress以监控请求的上传进度

<input type="file" name="file1" id="file1" style="display:none">
<button id="btn">上传文件</button>
<div id="pro"></div>
<div id="result"></div>
<script>
btn.onclick = function(){
file1.click();
pro.innerHTML = result.innerHTML = '';
}
file1.onchange = function(){
//创建xhr对象
var xhr;
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}else{
xhr = new ActiveXObject('Microsoft.XMLHTTP');
}
var data = file1.files[0];
//上传事件
xhr.upload.onprogress = function(e){
e = e || event;
if (e.lengthComputable){
pro.innerHTML = "上传进度为:" + e.loaded + " of " + e.total + " bytes" + ';百分比为:' + e.loaded/e.total;
}
}
xhr.onload = function(e){
var data = xhr.responseText;
e = e || event;
if(xhr.status == 200){
result.innerHTML = data;
}
};
//发送请求
xhr.open('post','pp.php',true);
xhr.setRequestHeader("content-type",data.type);
xhr.send(data);
}
</script>
<?php
error_reporting(E_ALL & ~E_NOTICE);
touch($file);
if(preg_match('/image/',apache_request_headers()['content-type'])){
$file = 'photo/test.jpg';
binary_to_file($file);
echo '文件上传成功!';
}else{
echo '文件格式不正确,请选择图片文件';
}
function binary_to_file($file){
$content = $GLOBALS['HTTP_RAW_POST_DATA']; // 需要php.ini设置
if(empty($content)){
$content = file_get_contents('php://input'); //不需要php.ini设置,内存压力小
}
$ret = file_put_contents($file, $content, true);
return $ret;
};
?>

其他事件

  HTTP请求无法完成有3种情况,对应3种事件。如果请求超时,会触发timeout事件。如果请求中止,会触发abort事件。最后,像太多重定向这样的网络错误会阻止请求完成,但这些情况发生时会触发error事件

  可以通过调用XMLHttpRequest对象的abort()方法来取消正在进行的HTTP请求。调用abort()方法在这个对象上触发abort事件

  调用abort()的主要原因是完成取消或超时请求消耗的时间太长或当响应变得无关时。假如使用XMLHttpRequest为文本输入域请求自动完成推荐。如果用户在服务器的建议达到之前输入了新字符,这时等待请求不再有用,应该中止

  XHR对象的timeout属性等于一个整数,表示多少毫秒后,如果请求仍然没有得到结果,就会自动终止。该属性默认等于0,表示没有时间限制

  如果请求超时,将触发ontimeout事件

var xhr = new XMLHttpRequest();
btn.onclick = function(){
xhr.abort();
};
xhr.ontimeout = function(){
console.log('The request timed out.');
}
xhr.timeout = 100;
xhr.onabort = function(){
console.log("The transfer has been canceled by the user.");
}
xhr.onerror = function(){
console.log("An error occurred while transferring the file.");
}
xhr.onloadend = function(){
console.log("请求结束");
}

深入理解ajax系列第五篇——进度事件的更多相关文章

  1. 深入理解ajax系列第五篇

    前面的话 一般地,使用readystatechange事件探测HTTP请求的完成.XHR2规范草案定义了进度事件Progress Events规范,XMLHttpRequest对象在请求的不同阶段触发 ...

  2. 深入理解ajax系列第八篇——表单提交

    前面的话 在以前,网站的用户与后端交互的主要方式是通过HTML表单的使用.表单的引入在1993年,由于其简单性和易用性,直到电子商务出现之前一直保持着重要位置.理解表单提交,对于更深入地理解ajax是 ...

  3. 深入理解ajax系列第八篇

    前面的话 在以前,网站的用户与后端交互的主要方式是通过HTML表单的使用.表单的引入在1993年,由于其简单性和易用性,直到电子商务出现之前一直保持着重要位置.理解表单提交,对于更深入地理解ajax是 ...

  4. 深入理解ajax系列第四篇——请求实例

    前面的话 在使用ajax的过程中,常用的请求方式是GET和POST两种.本文将以实例的形式来详细说明这两种请求方式 GET GET是最常见的请求类型,最常用于向服务器查询某些信息.必要时,可以将查询字 ...

  5. 深入理解ajax系列第三篇——响应解码

    前面的话 我们接收到的响应主体类型可以是多种形式的,包括字符串String.ArrayBuffer对象.二进制Blob对象.JSON对象.javascirpt文件及表示XML文档的Document对象 ...

  6. 深入理解ajax系列第七篇——传递JSON

    前面的话 虽然ajax全称是asynchronous javascript and XML.但目前使用ajax技术时,传递JSON已经成为事实上的标准.因为相较于XML而言,JSON简单且方便.本文将 ...

  7. 深入理解ajax系列第七篇

    前面的话 虽然ajax全称是asynchronous javascript and XML.但目前使用ajax技术时,传递JSON已经成为事实上的标准.因为相较于XML而言,JSON简单且方便.本文将 ...

  8. 深入理解ajax系列第三篇

    前面的话 我们接收到的响应主体类型可以是多种形式的,包括字符串String.ArrayBuffer对象.二进制Blob对象.JSON对象.javascirpt文件及表示XML文档的Document对象 ...

  9. 深入理解ajax系列第四篇——FormData

    前面的话 现代Web应用中频繁使用的一项功能就是表单数据的序列化,XMLHttpRequest 2级为此定义了FormData类型.FormData为序列化表单以及创建与表单格式相同的数据提供了便利. ...

随机推荐

  1. 抓取QQ空间相册

    某天,想下载某人的相册,发现一张一张下载,工作量巨大,所以写了这个工具. 使用到的工具 Fiddler(抓包工具) python(脚本语言) intellij 步骤 分析包 获取相册分类链接信息 打开 ...

  2. github使用及代码同步

    github是近两年比较火的分布式版本控制工具,很多nb的开源项目代码都托管在github上,比如Facebook.JQuery.Node.js等等,这里简单介绍一下github使用方法以及和本地工程 ...

  3. python中关于局部变量与全局变量的认识

    1.函数内部的变量名如果第一次出现,且出现在=前面,即被视为定义一个局部变量,不管全局域中有没有用到该变量名,函数中使用的将是局部变量,例如: num = 100 def func(): num = ...

  4. (五)Hololens Unity 开发之 手势识别

    学习源于官方文档 Gestures in Unity 笔记一部分是直接翻译官方文档,部分各人理解不一致的和一些比较浅显的保留英文原文 (五)Hololens Unity 开发之 手势识别 HoloLe ...

  5. oracle 11G RAC会话故障转移测试

    目前接手的几个项目中,默认使用的oracle RAC数据库服务,均不能实现自动的会话转移,尤其是对于应用的长连接,一旦发生数据库故障,需要重启应用.实际11G具备会话迁移机制,为此做了如下配置测试,供 ...

  6. 64位win2003 IIS6运行32位的.NET程序

    做web服务迁移,从32位win2003迁移到64位win2003,数据库是32位Oracle在另外一台服务器上. 迁移之后数据库各种连不上,oracle的客户端32位的装完装64位的,odp.net ...

  7. 快速排序的C语言实现

    #include <stdio.h> int qSort(int a[],int i,int j) { int h = i; int r = j; int x = a[h]; int f ...

  8. IOS缓存管理之PINCache使用

    前言: 今年重点在于公司iOS架构的梳理工作,上周整理了http请求接口管理与解耦,接下来准备整理一下项目中的缓存处理,目前项目中使用的是PINCache,去年加入这个开源框架时并没有对这个框架进行了 ...

  9. VMware上安装MS-DOS 6.22之一:基本系统的安装

    在网上看了一遍,发现关于在VMware上安装DOS的教程比较少,并且还有很多人发问怎么在VMware上安装DOS.为了方便大家,我便把我实际安装DOS的步骤讲出来分享一下,当然这其中也参考了一些网上资 ...

  10. 我眼中的JAVA的那些数据结构应用

    能沉淀下来的东西,往往都很基础,整理了下JAVA中遇到的数据结构 目录大纲: 到目前接触到的 有几个说明: 可扩容数组 ArrayList 扩容数组的实现, 满了后扩容,扩容在1.5倍,通过copy过 ...