简单实现jQuery 风格的 Ajax
Ajax 已经是一个很老的话题了,现在各种框架都会有成熟的封装,使得开发人员可以以较低的学习成本就可以熟练的创建基于ajax技术的应用。
这里面的缺点也很明显,相当一部分开发人员对ajax底层的知识了解甚少,如果脱离框架,可能就会不知所措————
当然,这种情形一般不会发生在开发过程中,更多的出现在面试过程中~ 大家都懂。
看一百遍不如自己实现一遍,动手之前建议参考一下 w3cschool 的 AJAX 教程 简单基础实用。
今天要实现的是 模仿 jQuery 风格的 ajax 调用方式:
$.get(url,[data],[callback]); $.post(url,[data],[callback]);
最终完成的目标是像这样发起异步请求并且处理返回数据:
Ajax.get('get.php',{foo:'bar'},function(data){
onGet(data);
});
Ajax.post('post.php',{pre:'huvtx',last:'ZHONGWEN中文@##@太热teshuf'},function(data){
onPost(data);
});
开始动手,动手之前先思考一下代码如何组织 思考完了:
var Ajax = Ajax || {};
Ajax = (function(){
//如果有jQuery 的 ajax实现就直接用jQuery.ajax
if(window.jQuery && jQuery.ajax) return jQuery.ajax;
/*
*没有,还是用熟悉的单例模式完成对Ajax对象的配置
*xhrs 用来存放每次调用建立的xhr 对象,xhr不需要复用
*/
var it = {}, win = window, doc = document , xhrs = {};
it.createXhr = function(){
/*
*产生一个兼容大部分浏览器的XMLHttpRequest 对象
*return xhr;
*/
};
it.getXhr = function(t){
/*
*按照调用时间生成一个xhr对象 并存到 xhrs 中去
*需要调用 it.createXhr
*return xhrs[t];
*/
};
it.dataQuest = function(data){
/*
*将 data 对象转换为字符串
*{foo:bar,foo2:bar2} => foo=bar&foo2=bar2
*如果传进来的是字符串 保持原样
*return string;
*/
};
it.mixUrl = function(url,query){
/*
*把url 和 quest 链接起来
*return url;
*/
};
it.request = function(method, url, data, callback, async){
/*
*创建一个xhr 并发送一个请求
*method string [GET]|[POST]
*url string
*data string|object
*callback function
*async true | false true 为异步
*/
/*
*主要几步如下 记不住的话可以简称为 COOS:
*createXhr open onreadystatechange send
*/
var xhr = it.getXhr(t);
xhr.open(method, url, syn);
xhr.onreadystatechange = function(e){ };
/*
*如果是POST 方式 sentData 需要有值
*如果想像提交表单一样提交 需要如下设置 requestHeader
*如果是GET 方式 sentData 可以不传,或者为 null
*/
if(method == 'POST'){
sentData = quest;
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
};
xhr.send(sentData);
};
/*
*get 方法实现 调用 request方法
*/
it.get = function(url,data,callback,async){
it.request('GET', url, data, callback, async);
};
/*
*post 方法实现 调用 request方法
*/
it.post = function(url, data, callback, async){
it.request('POST', url, data, callback, async);
};
/*
*清除使用完的xhr 对象
*/
it.clearXhr = function(t){
if(xhrs[t]){
xhrs[t].onreadystatuschange = null;
xhrs[t] = null;
}
};
/*
* 简单的trim 用于处理 responseText
*/
it.trim = function(s){
return s.replace(/(^\s*)|(\s*$)/g,'');
};
/*
*配置完成 返回 Ajax 对象
*/
return it;
})();
完整代码:
var Ajax = Ajax || {};
Ajax = (function(){
var it = {}, win =window , doc = document , xhrs = {};
it.createXhr = function(){
var xhr = null;
if(win.XMLHttpRequest){
try{
xhr = new XMLHttpRequest()
}catch(e){
xhr = null;
}
}else {
try{
xhr = new ActiveXObject('Msxml2.XMLHTTP');
}catch(e){
try{
xhr = new ActiveXObject('Microsoft.XMLHTTP');
}catch(e){
xhr = null;
}
}
}
return xhr;
};
it.getXhr = function(t){
if(xhrs[t]) return xhrs[t];
xhrs[t] = it.createXhr();
return xhrs[t];
};
it.dataQuest = function(data){
var quest = '';
if(typeof data == 'string'){
quest = data;
}else if(typeof data == 'object'){
var parms = [];
for(var o in data){
parms.push(o+'='+ encodeURIComponent( data[o]));
};
quest = parms.join('&');
};
return quest;
};
it.mixUrl = function(url,query){
url+= url.indexOf('?') > 0 ? '&' : '?';
url+= query;
return url.replace(/(\?)+/g,'?').replace(/(\&)+/g,'&');
};
it.request = function(method, url, data, callback, async){
var t = new Date()*1,
xhr = it.getXhr(t),
sentData = null,
quest = it.dataQuest(data),
syn = (typeof async == 'undefined') ? true : async;
if(method == 'GET'){
url = it.mixUrl(url,quest);
};
xhr.open(method, url, syn);
xhr.onreadystatechange = function(e){
//alert(xhr.status);
if(xhr.readyState == 4){
if(xhr.status >=200 && xhr.status < 400){
var data = it.trim(xhr.responseText);
if(data && typeof callback == 'function'){
callback(data);
setTimeout(function(){
it.clearXhr(xhr);
},0);
}
}
}
};
if(method == 'POST'){
sentData = quest;
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
};
xhr.send(sentData);
};
it.get = function(url,data,callback,async){
it.request('GET', url, data, callback, async);
};
it.post = function(url, data, callback, async){
it.request('POST', url, data, callback, async);
};
it.clearXhr = function(t){
if(xhrs[t]){
xhrs[t].onreadystatuschange = null;
xhrs[t] = null;
}
};
it.trim = function(s){
return s.replace(/(^\s*)|(\s*$)/g,'');
};
return it;
})();
调用方法:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>ajax test</title>
<script src="at.js"></script>
</head>
<body>
<script>
function getTest(){
Ajax.get('get.php',{foo:'bar'},function(data){
alert(data);
})
};
function postTest(){
Ajax.post('post.php',{pre:'huvtx',last:'ZHONGWEN中文@##@太热teshuf'},function(data){
alert(data);
})
};
</script>
<button onClick="getTest()">GET</button>
<button onClick="postTest()">POST</button>
</body>
</html>
看看服务端干了些啥:
/* *get.php 太简陋了 */ <?php $foo = $_GET['foo']; echo 'your foo is ~'.$foo; ?> /* *post.php 更简陋~ */ <?php $pre = $_POST['pre']; $last = $_POST['last']; echo $pre.$last; ?>
完~
最后补充几点相关的文章:
关于GET 和 POST 的区别
http://www.nowamagic.net/librarys/veda/detail/1919
不再以讹传讹,GET和POST的真正区别
网上的多数答案都是错的
http://www.yining.org/2010/05/04/http-get-vs-post-and-thoughts/
# 从HTTP GET和POST的区别说起
浙公网安备 33010602011771号