XMLHttpRequest
一开始只是微软浏览器提供的一个接口,后来各大浏览器纷纷效仿也提供了这个接口,再后来W3C对它进行了标准化,提出了XMLHttpRequest标准。XMLHttpRequest
标准又分为Level 1
和Level 2
。XMLHttpRequest Level 1
主要存在以下缺点:
那么Level 2
对Level 1
进行了改进,XMLHttpRequest Level 2
中新增了以下功能:
-
可以发送跨域请求,在服务端允许的情况下;
-
支持发送和接收二进制数据;
-
新增formData对象,支持发送表单数据;
-
发送和获取数据时,可以获取进度信息;
-
可以设置请求的超时时间;
当然更详细的对比介绍,可以参考阮老师的这篇文章,文章中对新增的功能都有具体代码示例。
XMLHttpRequest
兼容性
关于xhr
的浏览器兼容性,大家可以直接查看“Can I use”这个网站提供的结果XMLHttpRequest兼容性,下面提供一个截图。
从图中可以看到:
-
IE8/IE9、Opera Mini 完全不支持
xhr
对象 -
IE10/IE11部分支持,不支持
xhr.responseType
为json
-
部分浏览器不支持设置请求超时,即无法使用
xhr.timeout
-
部分浏览器不支持
xhr.responseType
为blob
细说XMLHttpRequest
如何使用
先来看一段使用XMLHttpRequest
发送Ajax
请求的简单示例代码。
-
function sendAjax() {
-
//构造表单数据
-
var formData = new FormData();
-
formData.append('username', 'johndoe');
-
formData.append('id', 123456);
-
//创建xhr对象
-
var xhr = new XMLHttpRequest();
-
//设置xhr请求的超时时间
-
xhr.timeout = 3000;
-
//设置响应返回的数据格式
-
xhr.responseType = "text";
-
//创建一个 post 请求,采用异步
-
xhr.open('POST', '/server', true);
-
//注册相关事件回调处理函数
-
xhr.onload = function(e) {
-
if(xhr.status == 200||xhr.status == 304){
-
alert(this.responseText);
-
}
-
};
-
xhr.ontimeout = function(e) { ... };
-
xhr.onerror = function(e) { ... };
-
xhr.upload.onprogress = function(e) { ... };
-
//发送数据
-
xhr.send(formData);
-
}
上面是一个使用xhr
发送表单数据的示例,整个流程可以参考注释。
接下来我将站在使用者的角度,以问题的形式介绍
xhr
的基本使用。
我对每一个问题涉及到的知识点都会进行比较细致地介绍,有些知识点可能是你平时忽略关注的。
如何设置request header
在发送Ajax
请求(实质是一个HTTP请求)时,我们可能需要设置一些请求头部信息,比如content-type
、connection
、cookie
、accept-xxx
等。xhr
提供了setRequestHeader
来允许我们修改请求 header。
void setRequestHeader(DOMString header, DOMString value);
注意点:
-
方法的第一个参数 header 大小写不敏感,即可以写成
content-type
,也可以写成Content-Type
,甚至写成content-Type
; -
Content-Type
的默认值与具体发送的数据类型有关,请参考本文【可以发送什么类型的数据】一节; -
setRequestHeader
必须在open()
方法之后,send()
方法之前调用,否则会抛错; -
setRequestHeader
可以调用多次,最终的值不会采用覆盖override
的方式,而是采用追加append
的方式。下面是一个示例代码:
-
var client = new XMLHttpRequest();
-
client.open('GET', 'demo.cgi');
-
client.setRequestHeader('X-Test', 'one');
-
client.setRequestHeader('X-Test', 'two');
-
// 最终request header中"X-Test"为: one, two
-
client.send();
如何获取response header
xhr
提供了2个用来获取响应头部的方法:getAllResponseHeaders
和getResponseHeader
。前者是获取 response 中的所有header 字段,后者只是获取某个指定 header 字段的值。另外,getResponseHeader(header)
的header
参数不区分大小写。
DOMString getAllResponseHeaders();
DOMString getResponseHeader(DOMString header);
这2个方法看起来简单,但却处处是坑儿。
你是否遇到过下面的坑儿?——反正我是遇到了。。。
-
使用
getAllResponseHeaders()
看到的所有response header
与实际在控制台Network
中看到的response header
不一样 -
使用
getResponseHeader()
获取某个header