昨天在使用Jquery的ajax请求时,在控制台打印了XMLHttpRequest对象,发现这个对象里面很多属性和方法比较陌生,所以花了一段时间研究了下XMLHttpRequest对象,参考了一篇有价值的文章,你真的会使用XMLHttpRequest吗?,学习内容如下。
XMLHttpRequest标准
XMLHttpRequest标准分为Level 1和Level 2。
XMLHttpRequest Level 1主要存在以下缺点:
* 受同源策略的限制,不能发送跨域请求;
* 不能发送二进制文件(如图片、视频、音频等)(Blob二进制数据),只能发送纯文本数据;
* 在发送和获取数据的过程中,无法实时获取进度信息,只能判断是否完成;
XMLHttpRequest Level 2中新增了以下功能:
* 可以发送跨域请求,在服务端允许的情况下;
* 支持发送和接收二进制数据;
* 新增formData对象,支持发送表单数据;
* 发送和获取数据时,可以获取进度信息;
* 可以设置请求的超时时间;
使用XMLHttpRequest对象来发送一个Ajax请求。
XMLHttpRequset对象
属性
属性 | 功能 |
---|---|
readyState | 存有服务器响应的状态信息,每当readyState改变时,onreadystatechange函数就会执行。 可能值有: 0,UNSENT,表示请求未初始化(在调用open()之前); 1,OPENED,请求已提出(调用send()之前); 2,HEADERS_RECEIVED,请求已发送(响应头和响应状态已返回); 3,LOADING,请求处理中(响应中通常有部分数据可用,但服务器还未完成响应); 4,DONE,请求已完成(可以访问服务器响应并使用它) |
response |
|
responseText |
|
responseXML |
|
onreadystatechange | 存储函数(或函数名),每当readyState属性改变时,就会调用这函数 |
status | 200:”OK” 404:未找到页面 |
responseType(level 2新增) | 指定xhr.reponse的数据类型 |
timeout(level 2新增) |
|
withCredentials(认证信息) | |
upload | 对象,属性有target(EventTarget)、type(DOMString)、bubbles(boolean)、cancelable(boolean)、lengthComputable(boolean)、loaded(unsigned long(long))、total(unsigned long(long)) |
指定xhr.reponse数据类型
xhr.overrideMimeType()
- server返回document或xml文档
- 设置xhr.overrideMimeType(‘text/xml; charset=utf-8’);
- xhr.reponse得到一个DOM对象。
xhr.responseType
reponseType值 | xhr.reponse数据类型 | 说明 |
---|---|---|
“” | String字符串 | 默认值 |
“text” | String字符串 | |
“document” | Document对象 | 希望返回XML数据时使用 |
“json” | JavaScript | IE10/11不支持 |
“blob” | Blob对象 | |
“arrayBuffer” | ArrayBuffer对象 |
获取response数据
XMLHttpRequest对象提供三个属性来获取请求返回数据,分别是:xhr.repsonse, xhr.reponseText, xhr.responseXML,
详情见XMLHttpRequest对象属性表。
发送同步请求
W3C的xhr标准中关于open()方法的说明:
Throws an "InvalidAccessError" exception if async is false, the JavaScript global environment is a document environment, and either the timeout attribute is not zero, the withCredentials attribute is true, or the responseType attribute is not the empty string.
当xhr为同步请求时,需满足如下条件:
- xhr.timeout必须为0
- xhr.withCredentials必须为false
- xhr.responseType必须为”“
获取上传、下载进度
可以通过onporgress事件来实时显示进度,默认情况下50ms触发一次。
- 上传触发的是xhr.upload对象的onprogress事件
- 下载触发的是xhr对象的onprogress事件
方法
方法 | 描述 |
---|---|
abort() | |
getResponseHeader(name) | |
open(method,url,async) |
|
overrideMimeType() | 重写reponse的content-type |
send(data) |
|
setRequestHeader(DOMString header, DOMString value) |
|
事件
事件 | 描述 |
---|---|
onloadstart | 调用xhr.send()方法后立即触发,未被调用则不会触发 |
onprogress | xhr.upload.onprogress在上传阶段(即xhr.send()之后,xhr.readystate=2之前)触发,每50ms触发一次;xhr.onprogress在下载阶段(即xhr.readystate=3时)触发,每50ms触发一次。 |
onload | 请求成功时触发,xhr.readystate=4 |
onabort | 调用xhr.abort()后触发 |
onloadend | 请求结束(包括请求成功和请求失败)时触发 |
onerror | 在请求过程中,若发生Network error则会触发此事件(若发生Network error时,上传还没有结束,则会先触发xhr.upload.onerror,再触发xhr.onerror;若发生Network error时,上传已经结束,则只会触发xhr.onerror)。注意,只有发生了网络层级别的异常才会触发此事件,对于应用层级别的异常,如响应返回的xhr.statusCode是4xx时,并不属于Network error,所以不会触发onerror事件,而是会触发onload事件。 |
ontimeout | xhr.timeout不等于0,从请求开始onloadstart开始算起,当到达xhr.timeout所设置时间请求还未结束即onloadend,触发此事件 |
onreadystatechange | 每当xhr.readystate改变时触发,但xhr.readystate由非0值变为0时不会触发 |
XMLHttpRequest事件接口实现代码
interface XMLHttpRequestEventTarget : EventTarget {
// event handlers
attribute EventHandler onloadstart;
attribute EventHandler onprogress;
attribute EventHandler onabort;
attribute EventHandler onerror;
attribute EventHandler onload;
attribute EventHandler ontimeout;
attribute EventHandler onloadend;
};
interface XMLHttpRequestUpload : XMLHttpRequestEventTarget {
};
interface XMLHttpRequest : XMLHttpRequestEventTarget {
// event handler
attribute EventHandler onreadystatechange;
readonly attribute XMLHttpRequestUpload upload;
};
XMLHttpRequest一共有8个事件:7个XMLHttpRequestEventTarget事件和一个onreadystatechange事件;XMLHttpRequestUpload只有7个XMLHttpRequesteEventTarget事件。
事件触发顺序
- 触发xhr.onreadystatechange(每次readyState变化时,都会触发一次)
- 触发xhr.onloadstart
//上传阶段开始 - 触发xhr.upload.onloadstart
- 触发xhr.upload.onprogress
- 触发xhr.upload.onload
- 触发xhr.upload.onloadend
//上传结束,下载阶段开始 - 触发xhr.onprogress
- 触发xhr.onload
- 触发xhr.onloadend
在哪个xhr事件中注册成功回调
xhr.onreadystatechange = function(){
if(xhr.readyState=4&&xhr.status==200){
//do successCallback
}
}
xhr.onload = function () {
//如果请求成功
if((xhr.status >= 200 && xhr.status <= 300) || xhr.status == 304){
//do successCallback
}
}