前言
XMLHttpRequest是一个浏览器接口,使得Javascript可以进行HTTP(S)通信。
最早,微软在 IE5 引进了这个接口。因为它太有用,其他浏览器也模仿部署了,ajax操作因此得以诞生。
此接口前后有两个版本,我们分别看这两个版本:老版本、新版本
老版本的XMLHttpRequest对象
老版本的用法如下:
- 首先,新建一个 XMLHttpRequest 的实例
var xhr
= new XMLHttpRequest();
- 然后,向远程主机发出一个 HTTP 请求:(先打开后发送)
xhr.open('GET', 'example.php'); // xhr.open(请求方式 , 请求 URL(GET 方式传参))
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); // 自定义头部字段
xhr.send(); // 发起请求,可传参(POST 方式传参)
- 接着,就等待远程主机做出回应。此时需要 监控 XMLHttpRequest 对象的
状态变化,指定回调函数
xhr.onreadystatechange = function(){
if ( xhr.readyState == 4 && xhr.status == 200 ) {
alert( xhr.responseText );
} else {
alert( xhr.statusText );
}
};
上面的代码包含了老版本 XMLHttpRequest 对象的主要属性:
- xhr.readyState:XMLHttpRequest 对象的
状态,等于4表示数据已经接收完毕。 - xhr.status:服务器返回的
状态码,等于 200 表示一切正常。 - xhr.responseText:服务器返回的
文本数据 - xhr.responseXML:服务器返回的
XML 格式的数据 - xhr.statusText:服务器返回的
状态文本。
老版本的缺点
老版本的 XMLHttpRequest 对象有以下几个缺点:
- 只支持文本数据的传送,无法用来读取和上传
二进制文件 - 传送和接收数据时,
没有进度信息,只能提示有没有完成 - 受到 "同源政策" 的影响 ,只能向
同一域名的服务器请求数据
新版本的功能
新版本的 XMLHttpRequest 对象,针对老版本的缺点,做出了大幅改进:
- 可以设置 HTTP 请求的
时限 - 可以使用 FormData 对象管理
表单数据 - 可以上传
文件 - 可以获得数据传输的
进度信息 - 可以请求不同域名下的数据(
跨域请求) - 可以获取服务器端的
二进制数据。
1. HTTP 请求的时限
有时,ajax操作很耗时,而且无法预知要花多长时间。如果网速很慢,用户可能要等很久。
新版本的 XMLHttpRequest 对象,增加了 timeout 属性,可以设置 HTTP 请求的时限
xhr.timeout = 3000;
上面的语句,将最长等待时间设为 3000 毫秒。过了这个时限,就 自动停止 HTTP 请求。与之配套的还有 ontimeout 事件,用来指定回调函数
xhr.ontimeout = function(event){
alert('请求超时!');
}
2. FormData 对象
ajax 操作往往用来传递表单数据。为了方便表单处理,HTML5新增了一个 FormData 对象,可以模拟表单
- 首先,新建一个 FormData 对象:
var formData = new FormData();
- 然后,为它添加表单项
formData.append('username', '张三');
formData.append('id', 123456);
- 最后,直接传送这个 FormData 对象。这与
提交网页表单的效果,完全一样
xhr.send(formData);
FormData 对象也可以用来获取网页表单的值
var form = document.getElementById('myform');
var formData = new FormData(form);
formData.append('secret', '123456'); // 添加一个表单项
xhr.open('POST', form.action);
xhr.send(formData); // 发送该表单
3. 上传文件
新版XMLHttpRequest对象,不仅可以发送文本信息,还可以上传文件。
假定files是一个"选择文件"的表单元素(input[type="file"]),我们将它 装入 FormData 对象,然后发送这个 FormData 对象
var formData = new FormData();
for (var i = 0; i < files.length;i++) {
formData.append('files[]', files[i]);
}
xhr.send(formData);
4. 获取进度信息
新版本的 XMLHttpRequest 对象,传送数据的时候,有一个 progress 事件,用来返回进度信息。
它分成上传和下载两种情况:
- 下载 的 progress 事件属于
XMLHttpRequest对象 - 上传 的 progress 事件属于
XMLHttpRequest.upload对象
- 先定义 progress 事件的回调函数
xhr.onprogress = updateProgress;
xhr.upload.onprogress = updateProgress;
- 然后,在回调函数里面,使用这个事件的一些属性
function updateProgress(event) {
if (event.lengthComputable) {
var percentComplete = event.loaded / event.total;
}
}
上面的代码中:
- event.total 是需要传输的总字节
- event.loaded 是已经传输的字节
- 如果 event.lengthComputable 不为真,则 event.total 等于 0
与 progress 事件相关的,还有其他五个事件,可以分别指定回调函数:
- load 事件:传输成功完成
- abort 事件:传输被用户取消
- error 事件:传输中出现错误
- loadstart 事件:传输开始
- loadEnd 事件:传输结束,但是不知道成功还是失败
5. 跨域资源共享(CORS)
新版本的XMLHttpRequest对象,可以向不同域名的服务器发出HTTP请求。这叫做"跨域资源共享"(Cross-origin resource sharing,简称 CORS)。
使用"跨域资源共享"的前提:1. 浏览器必须支持这个功能,而且 2. 服务器端必须同意这种"跨域"。如果能够满足上面的条件,则代码的写法与不跨域的请求完全一样
xhr.open('GET', 'http://other.server/and/path/to/script');
更多关于 CORS 的内容见 浏览器系列 -- 跨域