XMLHttpRequest(XHR)是一个JavaScript对象,最初由Microsoft设计,随后被Mozilla、Apple、Google采纳,如今已被W3C组织标准化,通过XHR对象可以获取一个URL链接上的资源数据。
XHR表示可扩展的超文本传输请求,它为客户端提供了在客户端和服务器之间传输数据的功能,简单来说它提供了一个可以通过URL链接地址来获取数据的方式,同时不会使整个页面刷新,使得页面中只更新部分而不会打扰到用户。XHR可以获取任何类型的数据,而不仅仅是XML,甚至支持HTTP以外的协议,比如file://
和FTP。
如果通信流程需要从服务器接收事件或消息数据,可通过EventSource接口使用server-sent events。对于全双工的通信,WebSocket则可能是更好地选择。
标准
XMLHttpRequest标准分为Level1和Level2两个阶段
XMLHttpRequest Level1 存在的缺点
- 受同源策略的限制不能发送跨域请求
- 不能发送二进制文件(如图片、视频、音频等)只能发送纯文本数据
- 发送和获取数据的过程中无法实时获取进度信息,只能判断是否完成。
XMLHttpRequest Level2 改进后新增
- 支持发送跨域请求,在服务器允许的情况下。
- 支持发送和接收二进制数据
- 新增
formData
对象支持发送表单数据 - 发送和获取数据时可以获取进度信息
- 可以设置请求超时事件
创建
// W3C标准中使用XMLHttpRequest对象
var xhr = new XMLHttpRequest();
// IE5、IE6使用ActiveX对象
var xhr = new ActiveXObject("Microsoft.XMLHTTP");
// 兼容写法
function xhr(){
var xhr;
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}else if(window.ActiveXObject){
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}else{
console.log("Your browser does not support XMLHTTP");
}
return xhr;
}
继承
XMLHttpRequest / XMLHttpRequestEventTarget / EventTarget
属性
属性 | 类型 | 描述 |
---|---|---|
readyState |
unsigned short |
请求的状态 |
onreadystatechange |
function |
JavaScript函数对象,当readyState 属性改变时会被调用。 |
response |
varies |
响应实体 |
responseType |
XMLHttpRequestResponseType |
期望服务器返回的响应格式 |
responseText |
DOMString |
请求的响应文本 |
status |
unsigned short |
请求的只读响应状态码 |
statusText |
DOMString |
请求的响应状态信息包含状态码和错误短语 |
upload |
XMLHttpRequestUpload |
在upload 上添加事件监听来跟踪上传过程 |
withCredentials |
boolean |
跨站cross-site 的访问控制Access-Control 请求时是否使用认证,默认false 。 |
timeout |
number |
请求超时事件 |
当发送出一个AJAX请求后,如果想要追踪请求当前处于哪种状态,应该怎么办呢?
使用xhr.readyState
属性可以追踪到AJAX请求的当前状态,此属性是只读属性,拥有5种可选值分别对应XHR对象不同阶段,每次xhr.readyState
属性值发生变化时,都会触发xhr.onreadystatechange
事件,可在事件中进行相关状态判断。
状态值 | 状态 | 含义 | 描述 |
---|---|---|---|
0 | UNSENT |
初始状态 未打开 | 此时XHR对象被成功构造,即open() 方法还未被调用。 |
1 | OPENED |
已打开 未发送 | 此时open() 方法已经被成功调用,send() 方法还未被调用,注意只有XHR处于OPENED 状态才能调用xhr.setRequestHeader() 方法和xhr.send() 方法,否则会报错。 |
2 | HEADERS_RECEIVED |
已获取响应头 | send() 方法已经被调用,响应头和响应状态已经返回。 |
3 | LOADING |
正在下载响应体 | 响应体response entity body 正在下载中,此状态下通过xhr.response 可能已经有了响应数据。 |
4 | DONE |
整个数据传输过程结束 | 整个数据传输过程结束,不管本次请求是成功还是失败。 |
每次readyState
属性值的改变都会触发onreadystatechange
事件,如果将onreadystatechange
事件处理函数赋给一个函数,那么每次readyState
状态值改变时都会调用该函数的执行。readyState
值的变化会因浏览器的不同而有所差异,但是当请求结束时每个浏览器都回将readyState
的值统一设置为4。
xhr.onreadystatechange
是一个事件句柄,值(state_change)是一个函数的名称,当XMLHttpRequest对象的状态发生改变时,会触发此函数,状态从0(uninitialized)到4(complete)进行变化,仅在状态为4时才执行代码。
XHR对象提供了三个属性来获取请求返回的数据,分别是xhr.response
、xhr.responseText
、xhr.responseXML
。
-
xhr.response
属性的默认值为空字符串,当请求完成时此属性才拥有正确的值,当请求未完成时此属性的值可能是空字符串或null
,具体则会xhr.responseType
有关,当xhr.responseType
为空字符串或text
时值为空字符串,当responseType
为其他值时response
的值为null
。 -
xhr.responseText
属性的默认值为空字符串,只有当responseType
为text
或空字符串时,XHR对象才拥有此属性,此时才会调用xhr.responseText
属性,否则会抛出错误。只有当请求成功时,才能拿到正确值。 -
xhr.responseXML
属性的默认值为null
,只有当responseType
为text
、document
、空字符串时XHR对象才具有responseXML
属性,否则会抛出错误。只有当请求成功且返回数据被正确解析时才能获得正确值,当请求未完成、请求失败、请求成功但返回数据无法被正确解析时会返回null
。
接收响应
当使用XMLHttpRequest对象的方法向服务器发送请求时,在AJAX处理过程中XMLHttpRequest对象可能被服务器更改readyState
、status
、responseText
、responseXML
属性。
状态码status
当服务器发送的每一个响应都会带有首部信息,其中三位数字的状态码status
是服务器发送的响应中最重要的字段,它属于超文本传输协议中的一部分。
常用状态码
状态码 | 状态 | 含义 |
---|---|---|
500 | internet server error | 内部服务器出错 |
404 | not found | 没有找到页面 |
403 | forbidden | 禁止访问 |
304 | not modified | 没有被修改 |
200 | ok | 一切正常 |
在XMLHttpRequest对象中服务器发送的状态码都保存在status
属性中,通过对状态码200和304进行比较可以确保服务器是否已经发送了一个成功的响应。
响应
响应类型 | 数据类型 | 说明 |
---|---|---|
"" |
String 字符串 |
默认值 |
text |
String 字符串 |
|
document |
Document 对象 |
返回XML格式数据使用 |
json |
JavaScript 对象 |
IE10/11不支持 |
blob |
Blob 对象 |
- |
arrayBuffer |
ArrayBuffer 对象 |
- |
方法
方法 | 功能 |
---|---|
abort() |
如果请求已经被发送则立即中止请求 |
getAllResponseHeaders() |
返回所有响应头信息(响应头名与值),若响应头未接收则返回null 。 |
getResponseHeader() |
返回指定的响应头的值,若响应头还没被接收或响应头不存在则返回null 。 |
open(method, url, async, user, password) |
初始化一个请求 |
overrideMimeType() |
重写由服务器返回的MIME type ,必须在send() 方法之前被调用。 |
send() |
发送请求,若是默认的异步请求则会立即返回,若是同步请求则直到请求的响应完全接收后才返回。 |
setRequestHeader() |
为指定的HTTP请求头设置值,使用前必须确保已经调用过open() 方法打开过一个URL。 |
使用XMLHttpRequest
对象与服务器进行通信时包含三个关键部分,分别是onreadystatechange
事件处理函数、open
方法、send
方法。
open(methoc, url, async, user, password)
XMLHttpRequest
对象的open()
方法允许开发人员使用一个AJAX调用向服务器发送请求
参数 | 值 |
---|---|
method |
请求所使用的HTTP方法,包括GET 、POST 、PUT 、DELETE 。若URL是非HTTP(S)的在可忽略method 。 |
url |
请求所要访问的URL |
async |
可选的布尔值参数,默认true 表示是否执行异步操作。值为false 则方法不返回,直到接收到服务器的返回数据。值为true 时会有一个对开发者透明的通知发送到相关的事件监听器上。 |
user |
可选,用户名,授权使用,默认为空字符串。 |
password |
可选,密码,授权使用,默认为空字符串。 |
void setRequestHeader(DOMString header, DOMString value);
当发送AJAX请求(实质是一个HTTP请求)时,可以根据需要设置请求的头部信息,比如Content-Type
、Connection
、Cookie
、Accept
等,XHR对象提供了setRequestHeader()
方法来允许修改请求的信息头Header
。
-
setRequestHeader
方法的第一个参数header
对大小写不敏感 -
Content-Type
的默认值与具体发送的数据类型有关 -
setRequestHeader
必须在open()
方法之后,send()
方法之前调用会抛错。 -
setRequestHeader
方法可以调用多次,最终的值不会采用覆盖的方式,而会采用追加的方式。
DOMString getAllResponseHeaders()
DOMString getResponseHeader(DOMString header)
XHR对象提供了两个用来获取响应头部的方法分别是getAllResponseHeaders
和getAllResponseHeader
getAllResponseHeaders
方法用于获取响应response
中所有头信息header
字段,需要注意的是getAllResponseHeaders()
方法只能拿到限制以外即被视为safe
安全的头信息header
字段,而非全部字段。getAllResponseHeader
方法只能获取某个指定头信息header
字段的值,此时方法的参数header
并不区分大小写。
W3C的XHR标准规定客户端无法获取响应response
中的Set-Cookie
和Set-Cookie2
两个字段,无论是同域或是跨域。
W3C的CORS标准对于跨域请求,规定客户端允许获取的响应信息头字段仅限于simple response header
和Accept-Control-Expose-Headers
。
事件
事件 | 触发 |
---|---|
onload |
当请求成功完成时触发 |
onloadstart |
当接收到响应数据时触发 |
onloadend |
当请求结束时触发,无论请求成功load 或失败abort 或error 。 |
onprogress |
当接收数据开始周期触发 |
onabort |
当请求被停止时触发 |
onerror |
当请求遭遇错误时触发 |
每个XMLHttpRequest
都拥有一个upload
属性,upload
本身是一个XMLHttpRequestUpload
对象,XMLHttpRequest
和XMLHttpRequestUpload
都继承自同一个XMLHttpRequestEventTarget
接口,所以upload
也具有上述事件。