原生Ajax总结
AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。
AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。
AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。
AJAX技术的核心是
XMLHTTPRequest
对象(XHR),虽然名字中有XML,但是Ajax通信与数据格式无关。
创建XHR对象
IE7+、Firefox、Opera、Chrome 和Safari 都支持原生的XHR 对象,使用XMLHttpRequest
构造函数。
var xhr=new XMLHttpRequest();//高版本
那么重点来了,我想要支持低版本的IE,那得怎么使呢,不着急,有妙招
首先检测原生XHR对象是否存在,如果存在则返回新实例。如果对象不存在,检查ActiveX对象。若都没有,那么,呵呵错误走你!
function createXHR() {
if (typeof XMLHttpRequest != 'undefined') {
return new XMLHttpRequest(); //高版本
} else if (typeof ActiveXObject != 'undefined') { //IE低版本
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');
}
}
使用XHR
在使用XHR对象时,必须调用open()方法,它有三个参数:要发送的请求类型(get、post)、请求的URL和表示是否异步。
xhr.open('get','dom.php',false);//对dom.php的get请求,false同步
open()方法并不会真正发送请求,而只是启动一个请求以备发送。通过send()方法进行发送请求,send()方法接受一个参数,作为请求主体发送的数据。如果不需要,必须填null,执行send()方法之后,请求就会发送到服务器上。
xhr.send(null);//发送请求
只能向同一个域中使用相同端口和协议的URL发送请求。如果URL与启动请求的页面有任何差别,都会引发安全错误。
当请求发送到服务器端,收到响应后,响应的数据会自动填充XHR对象的属性。共有四个属性:
属性名 | 说明 |
---|---|
responseText | 作为响应主体被返回的文本 |
responseXML | 如果响应主体内容类型是‘text/xml’或'application/xml ,则返回包含响应数据的XML DOM文档。 |
status | 响应的HTTP状态 |
statusText | HTTP状态说明 |
接受响应之后,第一步检查status属性,以确定响应已经成功返回。一般200为成功。
号 | 已定义范围 | 分类 |
---|---|---|
1xx | 100-101 | 信息提示 |
2xx | 200-206 | 成功 |
3xx | 300-305 | 重定向 |
4xx | 400-415 | 客户端错误 |
5xx | 500-505 | 服务器错误 |
HTTP状态码 | 状态字符串 | 说明 |
---|---|---|
200 | ok | 服务器成功返回了页面 |
301 | 永久转移 | |
302 | found | 资源暂时转移,常用于短连接转长连接 |
304 | Not Modified | 请求的资源没有被修改,允许直接使用浏览器中缓存的版本 |
400 | Bad Request | 语法错误导致服务器不识别 |
401 | Unauthorized | 请求需要用户认证 |
403 | Forbidden | 拒绝提供服务,可能发生在用户没有输入验证码的情况下 |
404 | Not found | 指定的URL在服务器上找不到 |
500 | Internal Server Error | 服务器遇到意外错误,无法完成请求 |
502 | Bad Gateway | 网关错误 |
503 | ServiceUnavaliable | 由于服务器过载或维护导致无法完成请求 |
xhr.open("get", "example.txt", false);
xhr.send(null);
if((xhr.status>=200&&xhr.status<300)||(xhr.status==304)){
alert(xhr.responseText);
}else{
alert(alert("Request was unsuccessful: " + xhr.status);
}
以上同步调用,简单,但是真正需要的是异步调用。使用异步调用的时候,需要触发readystatechange
事件,然后检测readyState的属性即可。
readyState值 | 状态 | 说明 |
---|---|---|
0 | 未初始化 | 尚未调用open(方法) |
1 | 启动 | 已经调用open()方法,但尚未调用send()方法 |
2 | 发送 | 已经调用send(),但尚未接受响应 |
3 | 接受 | 已经接受到部分响应数据 |
4 | 完成 | 已经接受到全部数据,而且可以使用 |
var xhr = createXHR();
xhr.onreadystatechange = function() {
if (readyState === 4) {//异步监控
if ((xhr.status >= 200 && xhr.status < 300) || (xhr.status == 304)) {
alert(xhr.responseText);
} else {
alert(alert("Request was unsuccessful: " + xhr.status);
}
}
};
xhr.open("get", "example.txt", true);//异步
xhr.send(null);
使用abort()方法可以取消异步请求,放在send()方法之前会报错。放在responseText
之前会得到一个空值。
get与post
首先来了解一下http头部信息,包含服务器返回的响应头信息和客户端发送出去的请求头信息。我们可以获取响应头信息或者设置 请求头信息。
名称 | 含义 |
---|---|
Accept | 浏览器能够处理的内容类型 |
Accept-Charset | 浏览器能够显示的字符集 |
Accept-Encoding | 浏览器能处理的压缩编码 |
Accept-Language | 浏览器当前设置的语言 |
Connection | 浏览器与服务器之间的连接类型 |
Cookie | 当前页面设置的任何Cookie |
Host | 发出请求的页面所在的域 |
Referer | 发出请求的页面的URL |
User-Agent | 浏览器的用户代理字符串 |
//使用getResponseHeader()获取单个响应头信息
alert(xhr.getResponseHeader('Content-Type'));
//使用getAllResponseHeaders()获取整个响应头信息
alert(xhr.getAllResponseHeaders());
//使用setRequestHeader()设置单个请求头信息
xhr.setRequestHeader('MyHeader', 'Lee'); //放在open 方法之后,send 方法之前
我们只可以获取服务器返回回来响应头信息,无法获取向服务器提交的请求头信息,自然定义的请求头,在Js端无法获取
get请求
get请求常用于向服务器查询某些信息。必要时,可以将查询字符串参数追加到URL的末尾,以便提交给服务器。
xhr.open('get','demo.php?rand='+Math.random()+'&name=koo',true)
通过URL后的问号给服务器传递键值对数据,服务器接收到返回响应数据。特殊字符
传参产生的问题可以使用encodeURIComponent()进行编码处理,中文字符的返回及传参,
可以将页面保存和设置为utf-8 格式即可。
function addURLParam(url, name, value){
url+=(url.indexOf('?')==-1?'?':'&');//判断的url 是否有已有参数
url+=encodeURLComponent(name)+'='+encodeURLComponent(value);
return url;
}
post请求
post请求可以包含非常多的数据,我们在使用表单提交的时候,大多使用post传输方式。
xhr.open('post','demo.php',true);
而发送post请求的数据,不会跟在url的尾巴上,而是通过send()方法向服务器提交数据
xhr.send('name=lee&age=18')
一般来说,向服务器发送post请求由于解析机制的原因,需要进行特别的处理。因为post请求和web表单提交不同,需要使用XHR来模仿表单提交。
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
从性能上来讲post请求比get请求消耗更多一些,用相同数据比较,get最多比post块2倍
封装ajax
function ajax(obj) {
var xhr = new createXHR();
obj.url = obj.url + '?rand=' + Math.random();
obj.data = params(obj.data);
if (obj.method === 'get') obj.url = obj.url.indexOf('?') == -1 ?
obj.url + '?' + obj.data : obj.url + '&' + obj.data;
if (obj.async === true) {
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) callback();
};
}
xhr.open(obj.method, obj.url, obj.async);
if (obj.method === 'post') {
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send(obj.data);
} else {
xhr.send(null);
}
if (obj.async === false) {
callback();
}
function callback () {
if (xhr.status == 200) {
obj.success(xhr.responseText); //回调
} else {
alert('数据返回失败!状态代码:' + xhr.status + ',
状态信息:' + xhr.statusText);
}
}
}
//调用ajax
addEvent(document, 'click', function () { //IE6 需要重写addEvent
ajax({
method : 'get',
url : 'demo.php',
data : {
'name' : 'Lee',
'age' : 100
},
success : function (text) {
alert(text);
},
async : true
});
});
//名值对编码
function params(data) {
var arr = [];
for (var i in data) {
arr.push(encodeURIComponent(i) + '=' + encodeURIComponent(data[i]));
}
return arr.join('&');
}
参考资料:JavaScript高级程序设计(第3版)