Ajax
Ajax技术的核心是XMLHttpRequest对象(简称XHR), XHR为向服务器发送请求和解析服务器响应提供了流畅的接口, 能过以异步的方式从服务器获取数据, 再通过DOM将新数据插入到页面中, 从而使得不用刷新页面也能获得新数据
XMLHttpRequest对象
现在的主流浏览器都支持原生的XHR对象, 如果要支持IE的早期版本(即IE7之前的版本), 那么可以这么写:
let createXHR = () = > {
// 首先检测原生XHR对象是否存在
if (typeof XMLHttpRequest != "undefined") {
return new XMLHttpRequest();
// 如果不存在原生对象, 则检测Active对象
} else if (typeof ActiveXObject != "undefined") {
if (typeof arguments.callee.activeXString != "string") {
let versions = [ "MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0",
"MSXML2.XMLHttp"], i, len;
for (i = 0; len = versions.length; i < len; i++) {
try {
new ActiveXObject(versions[i]);
argumnets.callee.activeXString = versions[i];
break;
} catch (ex) { console.log("Request was unsuccessful: " + xhr.status); }
}
}
return new ActiveXObject(arguments.callee.activeXString);
} else {
throw new Error("No XHR object avaiable.");
}
}
XHR的用法
在使用XHR对象时, 要调用的第一个方法是open(), 它接收五个参数: 要发送的请求的类型("get", "post"等), 请求的URL, 表示书否异步发送请求的布尔值, 以及最后两个可选参数: 用以服务端验证的账号密码(默认为null)
xhr.open("get", "example.php", fasle);
调用open函数后, 有两点需要注意:
-
- URL相对于执行代码的当前页面(也可以是 绝对路径)
-
- 调用open()方法并不会真正发送请求, 只是启动了一个请求以备发送
要发送特定的请求, 必须调用send()方法
xhr.open("get", "example.txt", false);
xhr.send(null);
这里的send()方法接收一个参数, 即要作为请求主体发送的数据. 如果不需要通过请求主题发送数据, 则必须传入null, 因为这个参数有对有些浏览器来说是必须的. 调用send()之后, 请求就会被分派到服务器.
当将open()的是否异步设置为fasle时, 代表此次请求是同步的, javascript代码会等到服务器响应之后再继续执行. 在收到响应后, 响应的数据会自动填充XHR对象的属性
- responseText: 作为响应主体被返回的文本
- responseXML: 如果响应的内容类型是"text/xml"或"application/xml", 这个属性中将保存包含着响应数据的XML DOM文档
- status: 响应的HTTP状态
- statusText: HTTPZ状态的说明
在接收到响应后, 第一步是检查status属性, 以确定响应已经成功返回. 一般来说, 可以将HTTP状态代码为200作为成功的标志. 此时responseText属性的内容已经就绪, 而且在内容类型正确的情况下, responseXML也应该能够访问了. 此外, 状态码为304表示请求的资源并没有被修改, 可以直接使用浏览器中缓存的版本. 为了确保能够接收到适当的响应, 应该这样检查上述两种状态码
xhr.open("get", "example.txt", false);
xhr.send(null);
if (xhr.status >= 200 && xhr.status < 300) || xhr.status == 304 {
// some code
} else {
console.log("Request was unsuccessful: " + xhr.status);
}
通过检测status来决定下一步的操作, 无论内容类型是什么, 响应主体的内容都会保存到responseText属性中; 而对于非XML数据而言, responseXML属性的值将为null
当open()方法设定发送的方式为异步请求时, onreadystatecharge事件监听器将自动在XMLHttpRequest对象的readyState属性改变时被触发, 该属性表示请求/响应过程的当前活动阶段, 这个属性的可取值如下:
- 0: 未初始化. 尚为调用open()方法
- 1: 启动. 已经调用open()方法, 但尚未调用send()方法
- 2: 发送. 已经调用send()方法, 但尚未接收到响应
- 3: 接收. 已经接收到部分响应数据
- 4: 完成. 已经接收到全部响应数据, 而且已经可以在客户端使用了
只要readyState属性的值由一个值变成另一个值, 都会触发一次readystatechange事件. 在调用open()之前指定onreadystatechange事件处理程序可以确保浏览器兼容性
let xhr = createXHR();
xhr.onreadystatechange = () => {
if (xhr.readyState == 4) {
if (xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
// some code
} else {
console.log("Request was unsuccessful: " + xhr.status);
}
}
};
xhr.open("get", "example.txt", true);
xhr.send(null);
在接收到响应之前可以调用abort()方法来取消异步请求
xhr.abort();
HTTP头部信息
默认情况下, 在发送XHR请求的同时, 还会发送下列头部信息
- Accept: 浏览器能够处理的内容类型
- Accept-Charset: 浏览器能够显示的字符集
- Accept-Encoding: 浏览器能够处理的压缩编码
- Accept-Language: 浏览器当前设置的语言
- Conection: 浏览器与服务器之间连接的类型
- Cookie: 当前页面设置的任何Cookie
- Host: 发出请求的页面所在的域
- Referer: 发出请求的页面的URL.(小彩蛋, HTTP规范将这个头部字段拼写错了, 正确的拼写方法应该是referrer)
- User-Agent: 浏览器的用户代理字符串
使用setRequestHeader()方法可以设置自定义的请求头部信息. 这个方法接收两个参数: 头部字段的名称和头部字段的值. 要成功发送请求头部信息, 必须调用
open()方法之后且调用send()方法之前调用setRequestHeader()
let xhr = createXHR();
xhr.onreadystatechange = () => {
if (xhr.readyState == 4) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
// some code
} else {
console.log("Request was unsuccessful: " + xhr.status);
}
}
}
xhr.open("get", "example.php", true);
xhr.setRequestHeader("MyHeader", "MyValue");
xhr.send(null);
调用XHR对象的getResponseHeader()方法并传入头部字段名称, 可以取得相应的响应头部信息. 而调用getAllResponseHeaders()方法则可以取得一个包含所有头部信息的长字符串
let myHeader = xhr.getResponseHeader("MyHeader");
let allHeaders = xhr.getAllResponseHeaders();
ajax的简单实现
let ajax = (url, method="GET", data = null, async = true) => {
// 声明XMLHttpRequest
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
console.log(`响应状态: ${xhr.status}`, "FINISH");
}
// 初始化请求参数
xhr.open(method, url, async);
// 发起请求
xhr.send(data);
}
}
ajax("https://www.google.com");
ajax("https://www.google.com", "POST", "A=1&B=2");