簡單實現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號