认识 XMLHttpRequest 2.0
XMLHttpRequest 1.0 API 存在以下缺陷。
- 只支持文本数据的传送,无法用来读取和上传二进制文件。
- 传送和接收数据时,没有进度信息,只能提示有没有完成。
- 受到同域限制,只能向同一域名的服务器请求数据。
2014 年 11 月 W3C 正式发布 XMLHttpRequest Level 2(http://www.w3.org/TR/XMLHttpRequest2/)标准规范,新增了很多实用功能,推动异步交互在 JavaScript 中的应用。说明如下:
- 可以设置 HTTP 请求的时限。
- 可以使用 FormData 对象管理表单数据。
- 可以上传文件。
- 可以请求不同域名下的数据(跨域请求)。
- 可以获取服务器端的二进制数据。
- 可以获得数据传输的进度信息。
请求时限
XMLHttpRequest 2.0 为 XMLHttpRequest 对象新增 timeout 属性,使用该属性可以设置 HTTP 请求时限。
xhr.timeout = 3000;
上面语句将异步请求的最长等待时间设为 3000 毫秒。超过时限,就自动停止 HTTP 请求。
与之配套的还有一个 timeout 事件,用来指定回调函数。
xhr.ontimeout = function (event) { console.log('请求超时!'); }
FormData 数据对象
在 JavaScript 中,XMLHttpRequest 2.0 新增 FormData 对象,使用它可以处理表单数据。
操作步骤
1) 新建 FormData 对象。
var formData = new FormData();
2) 为 FormData 对象添加表单项。
form.append('user', '张三'); form.append('pass', '123456');
3) 直接传送 FormData 对象。
xhr.send(formData);
4) FormData 对象也可以直接获取网页表单的值。
var form = document.getElementById('myform'); var formData = new FormData(form); formData.append('grade', '2'); //添加一个表单项 xhr.open('POST', 'form.action'); xhr.send(formData);
上传文件
新版 XMLHttpRequest 对象不仅可以发送文本信息,还可以上传文件。使用 send() 方法可以发送字符串、Document 对象、表单数据、Blob 对象、文件和 ArrayBuffer 对象。
示例
设计一个“选择文件”的表单元素(input[type="file"]),并将它装入 FormData 对象。
var formData = new FormData(); for (var i = 0; i < files.length; i ++){ formData.append('files[]', files[i]); }
然后,发送 FormData 对象给服务器。
xhr.send(formData);
跨域访问
XMLHttpRequest 2.0 版本允许向不同域名的服务器发出 HTTP 请求。使用跨域资源共享的前提是:浏览器必须支持这个功能,且服务器端必须同意这种跨域。如果能同时满足上面两个条件,则代码的写法与不跨域的请求完全一样。例如:
var xhr = createXHR(); var url = 'http://other.server/and/path/to/script'; //请求的跨域文件 xhr.open('GET', url, true); xhr.onreadystatechange = function () { if (xhr.readyState == 4 && xhr.status == 200) { console.log(xhr.responseText); } } xhr.send();
应用不同类型数据
新版本的 XMLHttpRequest 对象新增 responseType 和 response 属性。
- responseType:用于指定服务器端返回数据的数据类型,可用值为 text、arraybuffer、blob、json 或 document。如果将属性值指定为空字符串值或不使用该属性,则返回响应的数据。
- response:如果向服务器端提交请求成功,则返回响应的数据。
- 如果 responseType 为 text,则 response 返回值为一串字符串。
- 如果 responseType 为 arraybuffer,则 response 返回值为一个 ArrayBuffer 对象。
- 如果 responseType 为 blob,则 response 返回值为一个 Blob 对象。
- 如果 responseType 为 json,则 response 返回值为一个 JSON 对象。
- 如果 responseType 为 document,则 response 返回值为一个 Document 对象。
接收二进制数据
XMLHttpRequest 1.0 版本只能从服务器接收文本数据,而 XMLHttpRequest 2.0版本则可以接收二进制数据。使用新增的 responseType 属性,可以从服务器接收二进制数据。
可以把 responseType 设为 blob,表示服务器传回的是二进制对象。
var xhr = new XMLHttpRequest (); xhr.open('GET', '/path/to/image.png'); xhr.responseType = 'blob';
接收数据的时候,用浏览器自带的 Blob 对象即可。
var blob = new Blob ([xhr.response], {type : 'image/png'});
是读取 xhr.response,而不是 xhr.responseText。
可以将 responseType 设为 arraybuffer,把二进制数据装在一个数组里。
var xhr = new XMLHttpRequest (); xhr.open('GET', '/path/to/image.png'); xhr.responseType = 'arraybuffer';
接收数据的时候,需要遍历这个数组。
var arrayBuffer = xhr.response; if (arrayBuffer) { var byteArray = new Unit8Array (arrayBuffer); for (var i = 0; i < byteArray.byteLength; i ++ ) { //执行代码 } }
监测数据传输进度
新版本的 XMLHttpRequest 对象新增了一个 progress 事件,用来返回进度信息。它分成上传和下载两种情况。下载的 progress 事件属于 XMLHttpRequest 对象,上传的 progress 事件属于 XMLHttpRequest.upload 对象。
操作步骤
1) 先定义 progress 事件的回调函数。
xhr.onprogress = updateProgress; xhr.upload.onprogress = updateProgress;
2) 在回调函数里面,使用这个事件的一些属性。
function updateProgress (event) { if (event.lengthComputable) { var percentComplete = event.loaded / event.total; } }
上面代码中,event.total 是需要传输的总字节,event.loaded 是已经传输的字节。如果 event.lengthComputable 不为真,则 event.total 等于 0。
与 progress 事件相关的,还有其他 5 个事件,可以分别指定回调函数。
- load:传输成功完成。
- abort:传输被用户取消。
- error:传输中出现错误。
- loadstart:传输开始。
- loadEnd:传输结束,但是不知道成功还是失败。
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/23331.html