以前我们讲解了关于ajax的基础知识,了解到怎样操作DOM、加载一个文档等。如果你不打算去做一个ajax的大型代码库,你可以不用理会该小节的内容。因为这是对于维护大型的代码库所必须的。
重构refactoring:下面我们讲解一下关于Ajax中关于代码的重构的问题,首先我们要清楚,重构的作用和目的:第一,重构不是增加新的代码,而是重写代码使它们变得更加清晰,易于维护;第二,重构是识别出通用的解决方案,并按照这种特定的模式来重新组织代码的过程。
既然是使代码易于维护和修改,正原理在我们的编程中非常常见的,就向我们在C#.net中为了输出一个alert框,我们会写这样一个函数:
protected
void
ShowMessage(
string
msg)

...
{
response.write(""<script>alert('"+msg+"');</script>);
}
然后我们会在用到的地方直接引用该函数,例如:
...
{
if(dr.Read())

...{
ShowMessage("登陆成功!");
Response.Write("<script>location="Passport.aspx"</script>");
}
}
道理是一样的,我们重构的过程就是封装原有的函数集成为一个整体,其在功能或引用方面具有一定的关系,当然我们这里的重构会有一定的区别,这与JavaScript语言的基本特征是分不开的。下面我们来看一下上一节加载文档的例子的重构过程及其代码:
既然我们要重构这代码,使其用起来的时候可以直接引用,那么我们就必须把起封装起来,这里我们使用“名字空间对象”,也就是我们C# 中所说的 namespace命名空间。
首先我们来声明命名空间对象: var net=new object();
接着我们来定义该命名空间内的全局变量:
net.READY_STATE_UNINTIALIZED=0;
net.READY_STATE_LOADING=1;
net.READY_STATE_LOADED=2;
net.READY_STATE_INTERACTIVE=3;
net.READY_STATE_COMPLETE=4;
其次,我们来说一下,onload、onerror是 Function对象,也就是说,它们是函数对象。上节说过,在我们的函数,sendRequest(url,params,HttpMethod)中,只有第一个是必须的参数,因为url包含着我们所要加载的数据的来源地址。params我们完全可以不传,即可以为null;HttpMethod默认的为"POST"方式,这里我们要来修改以下为“GET”。现在我们先来构造一个函数,当然也要属于net 命名空间。
net.ContentLoader=function(url,onload,onerror){ //声明net空间下的一个函数 ContentLoader
this.url=url; //将数据来源变量值赋给该函数内的 this.url变量
this.req=null; //声明空的XMLHttpRequset对象
this.οnlοad=onload;
this.οnerrοr=(onerror)?onerror:this.defaultError;
this.loadXMLDoc(url);
}
下面来构造请求的过程:
创建XMLHttpRequest对象,loadXMLDoc(url){};
发送信息对象:sendRequest(){};
请求状态监视对象:onReadyState(){};
默认错误处理对象:defaultError(){};
现在我们想了,上面的4个函数都会与net.ContentLoader中的变量定义有关,那我们怎么来重构这4个函数呢?
方法也不难,我们可以创建 net.ContentLoader的一个属性,就象我们可以给net创建了一个ContentLoader对象一样。下面我们来重构这4个函数:
net.ContentLoader.prototype={
loadXMLDoc:function(url){},
sendRequest:function(){},
onReadyState:function(){},
defaultError:function(){}
}
函数的重构到这里就结束了,可我们怎么获得加载的文档的内容呢?也就是说,我们到底有没有成功地加载数据呢?我们下面来把获得的内容输出来做下验证吧。
<
html xmlns
=
"
http://www.w3.org/1999/xhtml
"
>
<
head runat
=
"
server
"
>
<
title
>
无标题页
</
title
>
<
script type
=
"
text/javascript
"
src
=
"
ContentLoader.js
"
></
script
>
<
script type
=
"
text/javascript
"
>
function
myCallBack()

...
{
var contentloader=document.getElementById("ContentLoader");
contentloader.innerHTML=this.req.responseText;
//var data=document.createTextNode(this.req.responseText);
//contentloader.appendChild(data);
}
window.onload
=
function
()

...
{
var loader=new net.ContentLoader("data.txt",myCallBack);
}
</
script
>
</
head
>
<
body
>
<
form id
=
"
form1
"
runat
=
"
server
"
>
<
div id
=
"
ContentLoader
"
>
</
div
>
</
form
>
</
body
>
</
html
>
上面代码中的myCallBack函数是回调处理函数。
关于重构我们就先讲到这里了,如果你不打算去做或者管理一个ajax的大型代码库,你可以不用理会该小节的内容。因为这是对于维护大型的代码库所必须的。下面我们附加完整的重构后的代码:
前台代码就是上面的一段了,下面附加 ContentLoader.js的代码内容:
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!"
+" readyState:"+this.req.readyState
+" status: "+this.req.status
+" headers: "+this.req.getAllResponseHeaders());
}
下一节我们来讲解关于模式的问题。