原生JS实现Ajax异步请求
原生JS实现Ajax请求
XMLHttpRequest对象
在IE7以下的浏览器,不支持原生XHR对象,需要使用MSXML库中的XHR对象,有三种不同版本: MSXML2.XMLHttp、MSXML2.XMLHttp.3.0 和 MXSML2.XMLHttp.6.0。
如果要兼容这些浏览器,必须创建一个函数来处理兼容问题。
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.");
}
}
然后就可以使用var xhr = createXHR();
来在所有浏览器中创建XHR对象了。
XHR的用法
get请求
使用XHR对象,要调用的第一个方法是open()方法,用来初始化请求,接受三个参数,分别是请求类型、请求URL、是否异步发送请求。
xhr.open("get", "demo.php", true);
要发送get请求,必须接着调用send()方法:xhr.send(null);
。
由于是异步请求,需要检测一个状态,等待数据接收完毕再处理请求。这个状态通过readyState
来表示。
readyState的值可以取0/1/2/3/4,分别代表未初始化、启动、发送、接受、完成状态。每次readyState改变都会触发事件: readystatechange
。
注意,为了保证跨浏览器兼容性,需要在open方法之前指定 onreadystatechange
事件。
var xhr = createXHR();
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
alert(xhr.responseText);
} else {
alert("Request was unsuccessful: " + xhr.status);
}
}
};
xhr.open("get", 'demo.php', true);
xhr.send(null);
对于get请求URL的查询字符串参数,可以使用encodeURIComponent
来将参数转化为合法的URL。
function addURLParam(url, name, value){
url += (url.indexOf("?") == -1 ? "?" : "&");
url += encodeURIComponent(name) + "=" + encodeURIComponent(value);
return url;
}
post请求
与get请求不同的是,post请求需要在send方法中,传入数据参数。还需要设置http请求头信息,将Content-Type
设置为application/x-www-form-urlencoded
。
function submitData(id){
var xhr = createXHR();
xhr.onreadystatechange = function(){
if (xhr.readyState == 4){
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
alert(xhr.responseText);
} else {
alert("Request was unsuccessful: " + xhr.status);
}
}
};
xhr.open("post", "postexample.php", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
var form = document.getElementById(id); // 将ID为id的表单中的数据序列化后发送给服务器
xhr.send(serialize(form)); // 将表单数据序列化并发送
}
serialize
表单序列化函数:
function serialize(form){
var parts = [],
field = null,
i,
len,
j,
optLen,
option,
optValue;
for (i=0, len=form.elements.length; i < len; i++){
field = form.elements[i];
switch(field.type){
case "select-one":
case "select-multiple":
if (field.name.length){
for (j=0, optLen = field.options.length; j < optLen; j++){
option = field.options[j];
if (option.selected){
optValue = "";
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("&");
}
XMLHttpRequest进度事件
load
: 在接收到完整的响应数据时触发该事件。只支持IE8+以上的浏览器。
可以用来替代readystatechange
事件,响应接收完毕就触发load事件,因此没有必要去检查readyState
属性了。
var xhr = createXHR();
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", "demo.php", true);
xhr.send(null);
详情请见笔记: JavaScript高级程序设计: Ajax