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的區別說起