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的区别说起