今天主要总结一下自己对ajax(Asynchronous JavaScript XML)的一些看法。
- 其他链接
先show一张图

一、Ajax的灵魂 – XMLHttpRequest
XMLHttpRequest是整个Ajax技术的灵魂。可以说,没有XMLHttpRequest就没有Ajax。
- 下面讲一讲关于这个对象的浏览器兼容
ie7以下:有三个不同版本的XHR对象
MSXML2.XMLHttpMSXML2.XMLHttp.3.0MXSML2.XMLHttp.6.0IE7+、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:请求的URLisAsyn:表示是否异步发送请求的布尔值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);
}