您的位置:首页 > 其它

Ajax使用XML异步加载数据

2007-07-06 12:23 537 查看
在使用应用的时候,特别是独占式的应用,用户会持续地和应用进行交互,所以基于 Web的开发,网络延迟是一个很重要的因素,传统的web应用依赖于整个页面的重新加载。每一次发到服务器的调用都会打断用户的使用。这便需要异步加载数据来实现。

最早提供这种后台通信能力是使用 IFrame ,后来,XMLHttpRequest对象提供了更清晰和强大的功能。我们先来看一下这2个技术。

IFrame : I 字母代表的是“inline”,意味着它是另外一个文档布局的一部分。一个IFrame表现为DOM的一个元素,只要页面可见,我们就可以改变它的大小、移动、或者将它完全隐藏。关键是,我们使得了IFrame不可见,从表面来看,在不可见的元素里加载一些我们即将用到的数据,这并不影响用户当前的工作,这使得以后台方式获得数据成了可能。从此我们有了一种与服务器进行异步通讯的机制。虽然这只不过是一种 Hack 式的临时解决方案。

和其他的DOM元素一样,IFrame可以在HTML中声明,也可以使用 document.createElement()方法来创建。自然也可以通过getElementById()来获取它的引用。


<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">


<title>无标题页</title>


<script type="text/javascript">


window.onload=function()




...{


var iframe=document.getElementById("dataFeed");


var src="datafeeds/mydata.xml";


loadDataAsynchronously(iframe,src);


}


function loadDataAsynchronously(ifrmae,src)




...{


//...............以后再说这里的功能。


}




</script>


</head>


<body>


<form id="form1" runat="server">


<div>




<iframe id="dataFeed" style="width:0px; height:0px;"></iframe>




</div>


</form>


</body>


</html>





上面我们是通过前台的声明来创建了 IFrame ,当然也可以:


function fetchData()




...{


var iframe=document.createElement("iframe");


iframe.className="hiddenDataFeed";


document.body.appendChild(iframe);


var src=''datafeeds/mydata.xml";


loadDataAsynchronously(iframe,src);


}





设想、如果我们遵循创建IFrame来异步加载数据的话,随着应用的运行,将会创建出大量的IFrame,我们必须在用完的时候销毁它们,或者,就要实现一个类似于对象池(pooling)的机制。我们将在以后介绍到的设计模式中讲解关于对象池、队列以及其他用来保证大型应用流畅运转的机制。下面我们先来看一下关于异步加载的另一个可行的方案:

XMLDocument和XMLHttpRequest对象: 

XmLDocument和XMLHttpRequest并不是DOM的标准扩展,只是碰巧得到了多数浏览器的支持,它们的设计目的很明确,就是用来以后台方式获得数据。两者都是源自微软私有的ActiveX组件,可以在浏览器中作为JavaScript对象来访问。两者对象执行的功能很相似,只是 XMLHttpRequest对象可以更加精细地对请求进行控制,我们主要使用XMLHttpRequest。这里先来介绍一下 XMLDocument。


<script type="text/javascript">


function getXMLDocument() //用来创建XMLDocument对象




...{


var xDoc=null;


if(document.implementation && document.implementation.createDocument)




...{


xDoc=document.implementation.createDocument("","",null);//首先检查文档是否支持创建一个原生的XMLDocument对象所需的implementation属性。


//implementation中文意思是“执行”,名词。如果支持则创建。


}


else //如果没有找到implementation属性,则测试浏览器是否支持ActiveX对象。




...{


if(typeof ActiveXObject != "undefined")




...{


var msXmlAx=null;


try




...{


msXmlAx=new ActiveXObject("Msxml2.DOMDocument"); //如果支持ActiveX ,则先尝试第二版MSXML库来创建该对象。


}


catch(e)




...{


msXmlAx=new ActiveXObject("Msxml.DOMDocument");//如果不支持新版MSXML库,则使用旧版创建该对象。


}


xDoc=msXmlAx;


}


}


if(xDoc==null || typeof xDoc.load=="undefined")




...{


xDoc=null;//如果上面两种方式都不支持,则简单地返回空的XMLDocument对象。我们将在后面详细讲解怎么才能更加优雅地处理这种情况。


}


return xDoc;


}


</script>

在上述函数getXMLDocument()中,我们并没有试图去猜测浏览器的版本,而是直接检测特定的对象是否可用,这种方法也称作对象检测(object detection)。

下面我们来看 XMLHttpRequest对象:

同样,首先来创建XMLHttpRequest对象,使用对象检测,检测是否支持原生的XMLHttpRequest对象,如果不支持,则检测是否支持 ActiveX 对象,如果两个都不支持,则简单地返回null;


<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">


<title>无标题页</title>


<script type="text/javascript">


function getXMLHttpRequest()




...{


var xRequest=null;


if(window.XMLHttpRequest)




...{


xRequest=new XMLHttpRequest();


}


else if(typeof ActiveXObject != "undefined")




...{


xRequest=new ActiveXObject("Microsoft.XMLHTTP");


}


return xRequest;


}




</script>


</head>


<body>


<form id="form1" runat="server">


<div>




</div>


</form>


</body>


</html>

由上述代码,如果浏览器支持其中的一种,则我们就成功的创建了XMLHttpRequest对象。既然创建了对象,我们就要利用它,现在我们使用已经创建的XMLHttpRequest对象来向服务器发送数据。

通过XMLHttpRequest向服务器发送数据是一件很直接的事情,我们所要做的所有事情就是给它传递一个服务器页面的URL,这个页面将生成数据,如下:


<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">


<title>无标题页</title>


<script type="text/javascript">


function getXMLHttpRequest()




...{


var xRequest=null;


if(window.XMLHttpRequest)




...{


xRequest=new XMLHttpRequest();


}


else if(typeof ActiveXObject != "undefined")




...{


xRequest=new ActiveXObject("Microsoft.XMLHTTP");


}


return xRequest;


}




function sendRequest(url,params,HttpMethod)




...{


if(!HttpMethod)




...{


HttpMethod="POST";


}


var req=getXMLHttpRequest();


if(req)




...{


req.open(HttpMethod,url,true);


req.setRequestHeader("Content-Type","application/x-www-form-urlencoded");


req.send(params);


}


}


</script>


</head>


<body>


<form id="form1" runat="server">


<div>




</div>


</form>


</body>


</html>

通过上面代码,我们成功地向服务器发送了一个请求,一个HTTP请求主要由 首部信息 和可能包含一些数据或参数的主体部分组成。响应则通常包括返回页面的HTML标记。这里我们将HTTP方法设置为POST请求方法。

简单说一下,HTTP方法有 "GET"用来获取文档;"POST"用来提交HTML表单;除外W3C还规约了一些其他的通用方法, "HEAD"用来获取一个文件的首部信息;"PUT"用来向服务器上传文档;"DELETE"用来删除服务器上的文档。

sendRequest()方法中包含的第二个和第三个参数都是可选参数,大部分情况都用不上。默认使用POST方法来获取资源,在请求的主体部分不需要传递任何参数。起上述代码对请求进行设置后,会立即将控制权返还给我我们,与此同时网络和服务器则正忙着他们自己的任务。这对于提高响应能力很有好处,但是我们怎样才能知道请求完成了呢?下面我们来讲解下。

使用回调函数监视请求:

处理异步通信的第二部分是在代码中设置一个入口,以便在调用结束的时候,可以获取结果,这通常是通过分配一个回调函数来实现的。也就是说,在未来某个不确定的时刻,当结果返回的时候,将会执行这一段代码。象我们平时见到的,window.onload函数以及UI控件上的onkeypress、onmouseover等都是回调函数。

下面我们来看下一个简单的回调处理函数的代码:


<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">


<title>无标题页</title>


<script type="text/javascript">


var READY_STATE_UNINITIALIZED=0; //未初始化状态


var READY_STATE_LOADING=1; //正在载如状态


var READY_STATE_LOADED=2; //已载入状态标志


var READY_STATE_INTERACTIVE=3; //交互状态


var READY_STATE_COMPLETE=4; //完成


var req;


function getXMLHttpRequest()




...{


var xRequest=null;


if(window.XMLHttpRequest)




...{


xRequest=new XMLHttpRequest();


}


else if(typeof ActiveXObject != "undefined")




...{


xRequest=new ActiveXObject("Microsoft.XMLHTTP");


}


return xRequest;


}




function sendRequest(url,params,HttpMethod)




...{


if(!HttpMethod)




...{


HttpMethod="POST"; //设置数据发送模式为POST


}


req=getXMLHttpRequest(); //创建XMLHttpRequest实例


if(req)




...{


req.onreadystatechange=onReadyStateChange; //当载入的状态变化,交给onReadyStateChange来处理


req.open(HttpMethod,url,true);


req.setRequestHeader("Content-Type","application/x-www-form-urlencoded");


req.send(params);


}


}


function onReadyStateChange()




...{


var ready=req.readyState; //获取XMLHttpRequest对象实例当前的状态


var data=null;


if(ready==READY_STATE_COMPLETE)




...{


data=req.responseText; //如果请求发送已经完成,则将请求的数据内容保存在data变量中


}


else




...{


data="Loading...+["+ready+"]"; //如果请求发送尚未完成,则显示当前所处的状态


}


//.....do sth. with the data


}


</script>


</head>


<body>


<form id="form1" runat="server">


<div>




</div>


</form>


</body>


</html>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: