转载自:http://blog.csdn.net/killme2008/
《实战AJAX》中重构的xmlhttpRequest调用的使用方法
书中前三章重构了xmlhttpRequest的调用,很不错的基本框架,代码如下:
var net=new Object();
net.READY_STATE_UNINITIALIZED=0;
net.READY_STATE_LOADING=1;
net.READY_STATE_LOADED=2;
net.READY_STATE_INTERACTIVE=3;
net.READY_STATE_COMPLETE=4;
/*--- content loader object for cross-browser requests ---*/
net.ContentLoader=function(url,onload,onerror,method,params,contentType){
this.req=null;
this.onload=onload;
this.onerror=(onerror) ? onerror : this.defaultError;
this.loadXMLDoc(url,method,params,contentType);
}
net.ContentLoader.prototype.loadXMLDoc=function(url,method,params,contentType){
if (!method){
method="GET";
}
if (!contentType && method=="POST"){
contentType='application/x-www-form-urlencoded';
}
if (window.XMLHttpRequest){
this.req=new XMLHttpRequest();
} else if (window.ActiveXObject){
this.req=new ActiveXObject("Microsoft.XMLHTTP");
}
if (this.req){
try{
var loader=this;
this.req.onreadystatechange=function(){
net.ContentLoader.onReadyState.call(loader);
}
this.req.open(method,url,true);
if (contentType){
this.req.setRequestHeader('Content-Type', contentType);
}
this.req.send(params);
}catch (err){
this.onerror.call(this);
}
}
}
net.ContentLoader.onReadyState=function(){
var req=this.req;
var ready=req.readyState;
var httpStatus=req.status;
if (ready==net.READY_STATE_COMPLETE){
if (httpStatus==200 || httpStatus==0){
this.onload.call(this);
}else{
this.onerror.call(this);
}
}
}
net.ContentLoader.prototype.defaultError=function(){
alert("error fetching data!"
+"/n/nreadyState:"+this.req.readyState
+"/nstatus: "+this.req.status
+"/nheaders: "+this.req.getAllResponseHeaders());
}
本质上就是以OO的方式构造了一个net对象,通过它来实现AJAX调用,构造函数必需的就两个参数:URL和回调函数(也就是你要处理服务器返回文档的函数),其他就是参数,方法,返回类型等。
写了一个简单的例子调用这个框架:
<script type='text/javascript' src='ContentLoader.js'></script>
<script type='text/javascript'>
window.onload=function(){
var loader1=new net.ContentLoader("data.txt",displayResult);
}
function displayResult(){
var tmp=document.getElementById("hello");
var txt=this.req.responseText;
alert(txt);
var childEl=document.createElement("div");
var textNode=document.createTextNode(txt);
childEl.appendChild(textNode);
tmp.appendChild(childEl);
}
</script>
<div id="hello"></div>
此 例中的回调函数就是displayResult()方法,url为同个文件夹下面的data.txt,很简单的例子,显示data.txt中的内容。在其 他函数中,你完全可以通过this来调用net对象,如上例中this.req.responseText,具体不再详述
javascript实现Observer模式来管理多个事件回调
《实战ajax》第四章介绍了这样的一个模型,与java中的事件处理模型相一致,观察者——监听者模式,感觉很 酷:)。比如,我要对ID为mousemat的div标签的onclick事件增加两个事件writestatus()和drawThumbnail (),更新状态栏和重定位鼠标位置这两个事件,典型的代码应该像这样:
window.onload=function(){
var mat=document.getElementById('mousemat');
mat.onclick=mouseObserver;
cursor=document.getElementById('cursor');
}
function mouseObserver(event){
var e=window.event||event;
writeStatus(e)
drawThumbnail(e)
}
这样的方式目前看起来还算清晰,但是当事件增多时将不可避免地复杂起来,如果我们能像java中的事件处理模型那样直接addListener该多好,书中给出了例子:
window.onload=function(){
var mat=document.getElementById('mousemat');
cursor=document.getElementById('cursor');
var mouseRouter=new jsEvent.EventRouter(mat,"onclick");
mouseRouter.addListener(writeStatus);
mouseRouter.addListener(drawThumbnail);
}
引入了一个EventRouter对象,此对象完整代码如下:
requires extras-array.js
var jsEvent=new Array();
jsEvent.EventRouter=function(el,eventType){
this.lsnrs=new Array();
this.el=el;
el.eventRouter=this;
el[eventType]=jsEvent.EventRouter.callback;
}
jsEvent.EventRouter.prototype.addListener=function(lsnr){
this.lsnrs.append(lsnr,true);
}
jsEvent.EventRouter.prototype.removeListener=function(lsnr){
this.lsnrs.remove(lsnr);
}
jsEvent.EventRouter.prototype.notify=function(e){
var lsnrs=this.lsnrs;
for(var i=0;i<lsnrs.length;i++){
var lsnr=lsnrs[i];
lsnr.call(this,e);
}
}
jsEvent.EventRouter.callback=function(event){
var e=event || window.event;
var router=this.eventRouter;
router.notify(e)
}
这段代码并不难理解,实现了一个事件顺序数组,增加的监听器函数通过Function.call()调用。两个方法addListener和removeListener真正实现了清晰的事件模型。