乐趣区

深入理解ajax——进度事件

一般地,使用 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> <?phperror_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(“ 请求结束 ”);
}

退出移动版