现代浏览器都通过 XMLHttpRequest 构造函数原生支持XHR对象
let xhr = new XMLHttpRequest();
对于 IE7 以前
var xhr;
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest(); // ie7+ 标准化
}else{
xhr = new ActiveXObject('Microsoft.XMLHTTP') ;
}
使用 XHR
open()
- 参数
- 请求类型
- GET 简单请求
- POST 复杂请求 除GET之外
- GET 与 POST 差异
- POST 更安全
- POST 发送数据量大,GET 有 url 长度限制 (在规范中 GET 是没有长度限制,只是在浏览器的实现中有限制)
- IE 2083Byte / Firefox 65536Byte / Chrome 8182Byte / Safari 80000Byte / Opera 190000Byte
- POST 能发送更多的数据类型 各种类型的文件
- GET 只能发送 ASCII 字符
- encodeURI() / decodeURI() / encodeURIComponent() / decodeURIComponent() (URI 中具有特殊含义的 ASCII 标点符号进行转义)
- HEAD OPTIONS PUT DELETE CONNECT TRACT 为什么不用?
- 因为前后端分离,不是混编。如果使用会暴露行为的目的不安全。
- 现在前端不直接操作后端的数据(由后端处理),前端没有必要作一个请求方式。
- GET 与 POST 差异
- 请求 URL
- 是否异步的布尔值
- 请求类型
- 注意
- URL是相对于代码所在页面,也可以使用绝对 URL
- 调用 open() 不会实际发送请求,只为发送请求做好准备
- 只能访问同源URL
send()
- 参数 请求体发送的数据,不需要发送请求体必须传
null
等待响应后 XHR 对象的属性被填充上数据
- responseText 作为响应体返回的文本
- responseXML 如果响应内容类型是 “text/xml” 或 “application/xml”,就是包含响应数据的 XML DOM 文档
- status 响应的 HTTP 状态
- 收到响应要先检查status属性以确保响应成功(2xx 或者 304 直接拿取缓存)
- statusText 响应的 HTTP 状态描述
- readyStatus 表示当前处在请求/响应的过程在哪个阶段
- 0 未初始化(Uninitialized)尚未调用 open() 方法
- 1 已打开(Open)已经调用 open() 方法,尚未调用 send() 方法
- 2 已发送(Sent)已经调用 send() 方法,尚未收到响应
- 3 接收中(Receiveing)已经收到部分响应
- 4 完成(Complete)已经收到所有响应,可以使用
- readystatechange 事件 每次当 readyState 从一个值变成另一个值时触发
abort() 方法 取消异步请求
Accept:浏览器可以处理的内容类型。
- Accept-Charset:浏览器可以显示的字符集。
- Accept-Encoding:浏览器可以处理的压缩编码类型。
- Accept-Language:浏览器使用的语言。
- Connection:浏览器与服务器的连接类型。
- Cookie:页面中设置的Cookie。
- Host:发送请求的页面所在的域。
- Referer:发送请求的页面的URI。注意,这个字段在 HTTP 规范中就拼错了,所以考虑到兼容性也必须将错就错。(正确的拼写应该是 Referrer。)
- User-Agent:浏览器的用户代理字符串。
setRequestHeader()
- 为XHR对象设置响应头部
- 在 open() 之后 send(),调用 setRequestHeader(key,value)
getResponseHeader()
- 参数 key
- 从 XHR 对象获取响应头部
getAllResponseHeaders()
- 返回包含所有响应头部字符串
Date: Sun, 14 Nov 2004 18:04:03 GMT
Server: Apache/1.3.29 (Unix)
Vary: Accept
X-Powered-By: PHP/4.3.8
Connection: close
Content-Type: text/html; charset=iso-8859-1
GET 请求
在 URL 后添加查询字符串参数。查询字符串每个名和值都使用encodeURIComponent()
编码,所有键/值对以&分隔。function addURLParam(url, name, value) {
url += (url.indexOf("?") == -1 ? "?" : "&");
url += encodeURIComponent(name) + "=" + encodeURIComponent(value);
return url;
}
POST 请求
XHR 模拟表单提交
- ContentType 的头部设置为提交表单使用的内容类型: “application/x-www-formurlencoded”
xhr.setRequestHeader('ContentType', 'application/x-www-formurlencoded'
创建对应格式作请求体
- 字符串 ‘param1=a¶m2=b’
- 把 form 标签下的序列化为格式字符串 ```javascript function serialize(form) { let parts = []; let optValue;
for (let field of form.elements) { switch(field.type) { case “select-one”: case “select-multiple”:
if (field.name.length) {
for (let option of field.options) {
if (option.selected) {
if (option.hasAttribute){
optValue = (option.hasAttribute("value") ?
option.value : option.text);
} else {
optValue = (option.attributes["value"].specified ?
option.value : option.text);
}
parts.push(encodeURIComponent(field.name)} + "=" +
encodeURIComponent(optValue));
}
}
}
break;
case undefined: // 字段集 case “file”: // 文件输入 case “submit”: // 提交按钮 case “reset”: // 重置按钮 case “button”: // 自定义按钮
break;
case “radio”: // 单选按钮 case “checkbox”: // 复选框
if (!field.checked) {
break;
}
default:
// 不包含没有名字的表单字段
if (field.name.length) {
parts.push(`${encodeURIComponent(field.name)}=` +
`${encodeURIComponent(field.value)}`);
}
} return parts.join(“&”); }
- FormData 类型 便于表单序列化
```javascript
let data = new FormData(document.forms[0]);
data.append("name", "Nicholas");
- 不再需要给 XHR 显式设置请求头部,XHR 对于 FormData 实例能自动配置相应头部
- qs.stringify()
- 字符串 ‘param1=a¶m2=b’
- 发送请求体
xhr.send('param1=a¶m2=b');
XMLHttpRequest Level 2
- FormData 类型
- 超时 xhr.timeout
- 触发事件 timeout
overrideMimeType() 方法,重写 XHR 响应 MINE 类型
load 事件
load 事件替代 readystatechange 事件, 这样就不用检查 readyState 属性 了。
在响应接收完成后立即触发
event.target == xhr
不过,并不是所有浏览器都实现了这个事件的 event 对象。考虑 到跨浏览器兼容,还是需要像下面这样使用 XHR 对象变量:
let xhr = new XMLHttpRequest();
xhr.onload = function() {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
alert(xhr.responseText);
} else {
alert("Request was unsuccessful: " + xhr.status);
}
};
xhr.open("get", "altevents.php", true);
xhr.send(null);
progress
事件
- loadstart:在接收到响应的第一个字节时触发。
- progress:在接收响应期间反复触发。
- event 对象
- targetXHR 对象
- lengthComputable 布尔值,进度信息是否可能
- position 接收到的字节数
- totalSize 响应的 ContentLength 头部定义的总字节数
- event 对象
- error:在请求出错时触发。
- abort:在调用 abort() 终止连接时触发。
- load:在成功接收完响应时触发。
- loadend:在通信完成时,且在 error、abort 或 load 之后触发。
let xhr = new XMLHttpRequest();
xhr.onload = function(event) {
if ((xhr.status >= 200 && xhr.status < 300) ||
xhr.status == 304) {
alert(xhr.responseText);
} else {
alert("Request was unsuccessful: " + xhr.status);
}
};
xhr.onprogress = function(event) { // 为了保证正确执行,必须在调用 open()之前添加 onprogress 事件处理程序。
let divStatus = document.getElementById("status");
if (event.lengthComputable) {
divStatus.innerHTML = "Received " + event.position + " of " +
event.totalSize +
" bytes";
}
};
xhr.open("get", "altevents.php", true);
xhr.send(null);