今天主要总结一下自己对ajax
(Asynchronous JavaScript XML
)的一些看法。
- 其他链接
先show
一张图
一、Ajax的灵魂 – XMLHttpRequest
XMLHttpRequest
是整个Ajax
技术的灵魂。可以说,没有XMLHttpRequest
就没有Ajax
。
- 下面讲一讲关于这个对象的浏览器兼容
ie7以下
:有三个不同版本的XHR
对象
MSXML2.XMLHttp
MSXML2.XMLHttp.3.0
MXSML2.XMLHttp.6.0
IE7+
、Firefox
、Opera
、Chrome
和Safari
:支持原生的XHR
对象
- 完整版的
createXHR()
函数
function createXHR(){
if (typeof XMLHttpRequest != "undefined"){
return new XMLHttpRequest();
} else if (typeof ActiveXObject != "undefined"){
if (typeof arguments.callee.activeXString != "string"){
var 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]);
arguments.callee.activeXString = versions[i];
break;
} catch (ex){
//跳过
}
}
}
return new ActiveXObject(arguments.callee.activeXString);
} else {
throw new Error("No XHR object available.");
}
}
- 其实我们现在都不需要再兼容ie6、7那么低的版本了,因此可以直接按以下去创建
xhr
对象:
var xhr = new XMLHttpRequest();
- 以下是输出的
xhr
对象
二、xhr的用法
2.1 xhr.open()
xhr.open(method,url,isAsyn);
xhr.open()
接受三个参数:method
::要发送的请求的类型post
、get
url
:请求的URL
isAsyn
:表示是否异步发送请求的布尔值true
:异步false
:同步
xhr.open()
不会真正发送请求,而只是启动一个请求以备发送。简单来说,就是起到一个打开连接的作用。
在调用
open()
之前指定onreadystatechange
事件处理程序才能确保跨浏览器兼容性。即:须在调用onreadystatechange
事件后才能调用xhr.open()
。
2.2 xhr.send()
xhr.send(data|null);
xhr.send()
只接受一个参数:要作为请求主体发送的数据。- 如果不需要通过请求主体发送数据,则必须传入
null
,因为这个参数对有些浏览器来说是必需的。
- 如果不需要通过请求主体发送数据,则必须传入
- 调用
send()
之后,请求就会被分派到服务器
2.3 xhr.readyState属性
xhr.readyState
:表示请求或者响应过程的当前活动阶段。- 0:未初始化。尚未调用
open()
方法。 - 1:启动。已经调用
open()
方法,但尚未调用send()
方法。 - 2:发送。已经调用
send()
方法,但尚未接收到响应。 - 3:接收。已经接收到部分响应数据。
- 4:完成。已经接收到全部响应数据,而且已经可以在客户端使用了。
- 0:未初始化。尚未调用
2.4 xhr的readystatechange事件
xhr.readyState
属性与readystatechange
事件一起用。- 只要
readyState
属性的值由一个值变成另一个值,都会触发一次readystatechange
事件。 - 通常,我们只对
readyState = 4
有兴趣,因为此时所有数据已经接收完毕。
- 只要
xhr.onreadystatechange = function() {
if(xhr.readyState == 4 ) {
//...
}
};
2.5 xhr - 响应数据的相关属性
- xhr - 响应数据的相关属性
responseText
:作为响应主体被返回的文本。responseXML
:如果响应的内容类型是”text/xml
“或”application/xml
“,这个属性中将保存包含着响应数据的XML DOM
文档。status
:响应的HTTP
状态。statusText
:HTTP
状态的说明。
- 在接收到响应后,即:
readyState = 4
后要做的事情:- 检查
status
属性,以确定响应已经成功返回。200
:响应成功304
:表示请求的资源并没有被修改,可以直接使用浏览器中缓存的版本;当然,也意味着响应是有效的。
- 根据状态码做相应的事情
- 检查
xhr.onreadystatechange = function() {
if(xhr.readyState == 4 ) {
if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){
alert(xhr.responseText);
}
}
};
2.6 xhr.abort()
xhr.abort()
: 取消异步请求。- 调用这个方法后,
XHR
对象会停止触发事件,而且也不再允许访问任何与响应有关的对象属性。 - 在终止请求之后,还应该对
XHR
对象进行解引用操作。由于内存原因,不建议重用XHR
对象。
- 调用这个方法后,
xhr.abort();
三、方法
3.1 get
get
:向服务器查询某些信息。- 使用
get
方法时, 我们一般将查询字符串参数追加到URL
的末尾,以便将信息发送给服务器。- 查询字符串中每个参数的名称和值都必须使用
encodeURIComponent()
进行编码,然后才能放到 URL 的末尾;而且所有名-值对儿都必须由和号(&
)分隔
- 查询字符串中每个参数的名称和值都必须使用
xhr.open("get", "example.php?name1=value1&name2=value2", true);
- 辅助函数
addUrlParams
:向现有URL
的末尾添加查询字符串参数- 接受三个参数
url
:要添加参数的 URLname
:参数的值value
:参数的名称
- 接受三个参数
function addUrlParams (url, name, value) {
url += (url.indexOf("?") == -1 ? "?" : "&");
url += encodeURIComponent(name) + "=" + encodeURIComponent(value);
return url;
}
var url = "example.php";
//添加参数
url = addURLParam(url, "name", "Nicholas");
url = addURLParam(url, "book", "Professional JavaScript");
//初始化请求
xhr.open("get", url, false);
- 这个函数首先检查
URL
是否包含问号(以确定是否已经有参数存在)。- 如果没有,就添加一个问号。
- 否则,就添加一个和号。
- 然后,将参数名称和值进行编码,再添加到 URL 的末尾。
- 最后返回添加参数之后的 URL。
3.2 post
post
:用于向服务器发送应该被保存的数据。post
方法会将数据作为请求的主体发送出去post
请求的主体可以包含非常多的数据,而且格式不限
四、总结
其实使用Ajax
很简单,就4
步曲:
- 创建灵魂人物——
xhr
对象:var xhr = new XMLHttpRequest();
- 打开连接:
xhr.open(...)
- 发送数据:
xhr.send(...)
- 接收数据:
xhr.onreadystatechange
+xhr.readyState
+xhr.status
- 由于
Ajax
是异步的,所以onreadystatechange
事件是放在xhr.open()
之前的
- 由于
接下来是封装好的ajax函数
- es5
function ajax(config) {
// 创建 xhr对象
var xhr = new XMLHttpRequest(),
headers = config.headers || [];
// 接收数据
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) {
var data = JSON.parse(xhr.responseText);
config.fn && config.fn(data);
}
}
}
// 打开连接
xhr.open(config.method, config.url, config.isAsync || true);
// 自定义请求头
headers.forEach(function(item) {
xhr.setRequestHeader(item.name, item.value);
})
// 发送数据
xhr.send(config.data || null);
}
- es6
const ajax = (config) => {
const xhr = new XMLHttpRequest(),
headers = config.headers || [];
xhr.onreadystatechange = () => {
if (xhr.readyState == 4) {
if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) {
const data = JSON.parse(xhr.responseText);
config.fn && config.fn(data);
}
}
}
// 打开连接
xhr.open(config.method, config.url, config.isAsync || true);
// 自定义请求头
headers.forEach(function(item) {
xhr.setRequestHeader(item.name, item.value);
})
// 发送数据
xhr.send(config.data || null);
}