JS之AJAX-进度事件
通常情况下,使用readystatechange事件监听HTTP请求的完成。XHR2规范草案定义了进度事件Progress Events事件,XHR对象在请求的不同阶段触发不同类型的事件,所以不再需要检测readyState属性,该规范定义了客户端与服务端通信的有关事件。这些事件最早其实只针对XHR操作,但目前也被其他API(如File API)借鉴。
事件
loadstart: 在接收到响应数据的第一个字节时触发
progress: 在接收到响应期间持续不断的触发
error: 在请求发生错误时触发
abort: 在调用abort()方法终止连接使触发
load: 在接收到完整的响应数据时触发
loadend: 在通信完成,或者触发error、abort、load事件时触发
timeout: 在请求超时使触发
每个请求都从loadstart事件开始,接着每个50ms左右触发一次progress事件,然后触发error、abort、load或timeout事件中的一个,最后以触发loadend事件结束
对于任何请求,浏览器将只会触发error、abort、load或timeout事件中的一个。XHR2规范草案指出一旦这些事件中的一个发生后,浏览器应该触发loadend事件
注意: IE9-浏览器不支持以上事件(IE9浏览器仅支持load事件)
load事件
load事件会在响应接收完毕时触发,因此不用再去检查readyState属性了。但是请求完成不代表请求成功,所以还会使用XHR对象的status属性判断是否请求成功
xhr.onload = function(e) {
if(xhr.status == 200) {
console.log(xhr.responseText);
}
}
progrerss
progress事件会在接收到响应期间持续不断的触发,触发期间会接收到一个event对象,包含着四个属性:target属性是XHR对象、lengthComputable是一个表示进度信息是否可用的布尔值、loaded表示已经接收的字节数、total表示根据Content-Length响应头部确定的预期字节数。
下面是一个音乐文件的加载过程示例
<div id="result"></div>
<div id="music"></div>
<button id="btn">btn</button>
<script>
btn.onclick = function() {
var xhr = new XMLHttpRequest();
xhr.onprogress = function(e) {
if(e.lengthComputable) {
result.innerHTML = e.loaded + 'bytes / ' + e.total + 'bytes';
}
}
xhr.onload = function(e) {
var data = xhr.response;
if(xhr.status == 200) {
var audio = document.createElement('audio');
audio.onload = function() {
URL.revokeObjectURL(audio.src);
}
audio.src = URL.createObjectURL(data);
audio.setAttribute('controls', '');
if(!music.innerHTML) {
music.appendChild(audio);
}
}
}
xhr.open('GET', '/pfzl.mp3', true);
xhr.responseType = 'blob';
xhr.send();
}
</script>
上传进度
XHR2定义了XMLHttpRequest对象的upload属性,用于监控HTTP请求的上传事件。该属性的属性值是一个对象,它定义了addEventListener()方法和整个Progress Events事件集合
可以像使用progress事件处理程序一样使用upload事件处理程序。对于XMLHttpRequest对象,设置XHR.onprogress可以监控响应的下载进度,设置XHR.upload.onprogress可以监控请求的上传进度
下面是一个上传进度的示例
<input type="file" name="file" id="uploadInput" style="display: none;">
<div id="progress"></div>
<div id="result"></div>
<button id="btn">upload</button>
<script>
btn.onclick = function() {
uploadInput.click();
}
uploadInput.onchange = function() {
var file = uploadInput.files[0];
var xhr = new XMLHttpRequest();
xhr.upload.onprogress = function(e) {
if(e.lengthComputable) {
progress.innerHTML = e.loaded + 'bytes / ' + e.total + 'bytes';
}
}
xhr.onload = function(e) {
if(xhr.status == 200) {
if(!result.innerHTML) {
result.innerHTML = xhr.responseText;
}
}
}
xhr.open('POST', '/api/test', true);
xhr.setRequestHeader('Content-Type', file.type);
xhr.send(file);
}
其他事件
当HTTP请求无法完成时会有三种情况,对应三种不同的事件:
- 如果请求超时,会触发timeout事件
- 如果请求中止,会触发abort事件
- 网络错误会触发error事件
调用abort()方法可以取消正在进行的HTTP请求,该方法一旦调用,会触发abort事件。一个比较常见的应用场景,假如使用XMLHttpRequest为文本输入域请求自动完成推荐,如果用户在服务器的建议达到之前输入了新字符,这时等待请求不再有用,应该中止
XHR对象的timeout属性等于一个整数,表示多少毫秒后,如果请求仍然没有得到结果,就会自动终止并触发timeout事件。该属性默认等于0,表示没有时间限制
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("请求结束");
}