您的位置:首页 > 理论基础

如何使用AJAX----计算机世界报

2012-03-14 09:29 323 查看

如何使用AJAX



初次接触AJAX的开发人员一定很关心:如何在实际环境中使用 AJAX,以及如何评估它在项目中的价值。本文从基本操作入手,结合模拟实例,由浅入深介绍了AJAX的入门之道。

AJAX入门
● 如何发送HTTP请求
为了使用JavaScript向服务器发送HTTP请求,需要为提供这种功能的类创建实例。这种类最先作为ActiveX对象: XMLHTTP被引入到Internet Explorer里面。后来,Mozilla、Safari及其他浏览器纷纷仿效,实现了XMLHttpRequest类,支持微软的原始ActiveX对象所具有的方法和属性。

因此,为了为所需的类创建跨浏览器的实例(对象),可编写如下代码。(为了便于阐述,该代码是用于创建XMLHTTP实例的简化版。)
if (window.XMLHttpRequest) { // Mozilla, Safari, ...
http_request = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
http_request = new ActiveXObject("Microsoft.XMLHTTP");
}
如果来自服务器的响应没有XML mime-type头,一些Mozilla浏览器的某些版本可能无法正常工作。为了解决这个问题,如果服务器发送的头不是text/xml,可调用另外方法来忽略该头。

http_request = new XMLHttpRequest();
http_request.overrideMimeType('text/xml');
下一步就是确定收到服务器对请求的响应后,需要做什么。在这个阶段,需要告诉HTTP请求对象: 哪个JavaScript函数将完成处理响应的工作。可以把对象的onreadystatechange属性设成准备使用的JavaScript的函数的名称,如下所示:

http_request.onreadystatechange = nameOfTheFunction;
注意,函数名后面没有方括号,也无需传递参数。另外,可以使用迅速定义函数的Javascript技术,定义会立即处理响应的动作,而不是赋予函数名,如下所示:

http_request.onreadystatechange = function(){
// 完成工作};
声明了一旦收到响应会发生什么动作后,就要实际发送请求了。需要调用HTTP请求类的open()和send()方法,如下所示:
http_request.open('GET', 'http://www.example.org/some.file', true);

http_request.send(null);
open()调用的第一个参数是HTTP请求方法——GET、POST、HEAD或者其他任何得到服务器支持的方法。按照HTTP标准,方法需要大写,否则,有些浏览器(如Firefox)可能无法处理请求。第二个参数是请求页面的URL。作为一项安全特性,无法调用第三方域名上的页面。所有页面上务必使用准确的域名,否则如果调用open(),会得到“权限被拒绝”的错误提示。一个常见的错误就是按照domain.tld来访问网站,却试图使用www.domain.tld调用页面。第三个参数确定了请求是不是异步模式。如果是TRUE,那么即使服务器响应还没有到达,JavaScript函数仍继续执行。这就是AJAX中的“A”。

如果请求方法是POST,那么send()方法的参数可以是想发送给服务器的任何数据。数据应当采用查询字符串的格式,如下所示:
name=value&anothername=othervalue&so=on
注意,如果想使用POST发送请求,必须使用以下代码行来改变请求的MIME类型,否则,服务器会丢弃通过POST发送的数据。
http_request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

● 处理服务器响应
切记,在发送请求时,要提供旨在处理响应的JavaScript函数的名称。
http_request.onreadystatechange = nameOfTheFunction;
不妨看一下这个函数的功能。首先,函数需要检查请求的状态。如果状态的值为4,就意味着完整的服务器响应已收到,可以继续处理响应。readyState值如下: 0(未初始化)、1(正在加载)、2(加载完毕)、3(可以交互)、4(完成)。

if (http_request.readyState == 4) {
// 一切正常,响应已收到
} else {
// 还没有就绪
}
下一步就是检查HTTP服务器响应的状态代码。所有可能的状态代码都列在W3C的网站上(http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html)。这里只对200 OK响应感兴趣。

if (http_request.status == 200) {
// 非常好!
} else {
// 请求有问题,
// 譬如响应可能是404(未发现)
// 或者500(内部服务器错误)响应代码
}
检查了请求状态及响应的HTTP状态代码后,就可以对服务器发送过来的数据进行各种处理了。有两种方式来访问该数据: 一是http_request.responseText,将返回文本字符串形式的服务器响应; 二是http_request.responseXML,将返回XMLDocument对象形式的响应。可以用JavaScript DOM函数来遍历XMLDocument对象。

● 简单示例
我们把所有部分结合起来,发送简单的HTTP请求。我们的JavaScript将请求一个HTML文档: test.html,该文档包含“I'm a test.”文本,然后我们用alert()方法显示test.html文件的内容。

< script type="text/javascript" language="javascript">
var http_request = false;
function makeRequest(url) {
http_request = false;
if (window.XMLHttpRequest) { // Mozilla, Safari,...
http_request = new XMLHttpRequest();
if (http_request.overrideMimeType) {
http_request.overrideMimeType('text/xml'); }
} else if (window.ActiveXObject) { // IE
try {
http_request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
http_request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
if (!http_request) {
alert('Giving up :( Cannot create an XMLHTTP instance');
return false; }
http_request.onreadystatechange = alertContents;
http_request.open('GET', url, true);
http_request.send(null);
}
function alertContents() {
if (http_request.readyState == 4) {
if (http_request.status == 200) {
alert(http_request.responseText);
} else {
alert('There was a problem with the request.'); }
}
}
< /script>
< span
style="cursor: pointer; text-decoration: underline"
onclick="makeRequest('test.html')">
Make a request
< /span>
在这个示例中,用户点击浏览器上面的“发送请求”链接; 调用makeRequest()函数,参数是同一目录下的HTML文件名: test.html; 请求被发送,然后onreadystatechange执行结果被传递给alertContents();

alertContents()检查响应是否被收到、是否正常,然后用alert()方法显示test.html文件的内容。
如果XMLHttpRequest调用的页面不是有效的XML(譬如不是明文),上面的代码行“http_request.overrideMimeType('text/xml');”就会导致Firefox 1.5b里面出现Javascript 控制台错误信息。如果浏览器上出现了“语法错误”或者“不规范的错误”,而且不是试图从XMLHttpRequest加载XML页面,请从代码中删除该行。

另外,如果把请求发送到将返回XML的一段代码,而不是发送到静态的XML文件,要是页面在Mozilla和IE浏览器中都能正常工作,就必须设置一些响应头。如果没有设置头: “Content-Type: application/xml”,IE会在试图访问XML元素的那一行后面抛出Javascript错误: “Object Expected”。如果没有设置头: “Cache-Control: no-cache”,浏览器就会缓存响应,永远不会重新提交请求。这样一来,调试起来就会难度很大。

● 处理XML响应
在前一个示例中,收到HTTP请求的响应后,我们使用了请求对象的reponseText属性,该属性包含test.html文件的内容。现在我们来试一试responseXML属性。

首先,我们创建一个有效的XML文档,随后我们将对其发出请求。该文档(test.xml)含有以下代码:
< ?xml version="1.0" ?>

I'm a test.

在脚本中,我们只要修改请求代码行:
onclick="makeRequest('test.xml')">
然后在alertContents()中,我们需要把alert()代码行alert(http_request.responseText):

var xmldoc = http_request.responseXML;
var root_node = xmldoc.getElementsByTagName('root').item(0);
alert(root_node.firstChild.data);
这样一来,我们获得了responseXML提供的XMLDocument对象,然后我们使用DOM方法访问XML文件里面所含的一些数据。

何时使用AJAX
已经知道了AJAX的基本知识,下一步无疑就是确定要不要在项目中使用它。要记住的最重要一点就是,如果没有刷新页面,就无法使用“后退”按钮。要把注意力集中于项目中可能得益于使用这种交互的一小部分。譬如说,可以创建一个表单: 每当用户键入输入字段,或者键入字母,就可以查询脚本,以便提供实时验证功能。可以创建拖放页面: 一释放项目,就可以把数据发送到脚本中,并把页面状态保存到数据库。现在确实存在使用AJAX的理由,这不但有助于开发体验,还有助于用户,它完全取决于实际情况和执行状况。

还有其他方法可以避开“后退”按钮方面的问题,譬如使用Google Gmail: 它现在可以为已经完成的操作步骤提供撤消功能,用不着刷新页面。以后肯定会出现许多更有创意的例子,为开发人员提供诸多方法来创建独特、实时的体验,从而让用户成为受益者。

假定读者已经对AJAX的JavaScript和XML两个部分有一定了解。虽然开发人员可以通过AJAX请求任何类型的文本文件,但这里将着重讨论XML类型。本文创建了一个示例项目。这个示例是一个简单的请求,要求加载含有页面内容的XML文件,然后解析数据,把它显示在HTML页面上。

表1和表2介绍了Windows Internet Explorer 5、Mozilla、Netscape 7、Safari 1.2和Opera支持的属性和方法。





● 从何处开始
首先,需要创建一个XML文件,随后我们会对其进行请求,并作为页面内容来解析。这里请求的那个文件必须与完成的项目位于同一服务器上。
下一步,创建将发出请求的HTML文件。页面使用主体标记中的装载方法进行装载时,就会发生请求。然后,文件需要带有ID的div标记,那样我们准备好显示内容后,就可以确定目标。完成了这些步骤后,页面主体的样子应当如下:

<body onload="makeRequest('xml/content.xml');">
<div id="copy"></div>
</body>
● 创建请求对象
为了创建请求对象,必须检查浏览器使用的是XMLHttpRequest还是ActiveXObject。这两个对象之间的区别主要在于使用它们的浏览器。Windows IE 5 及以上版本使用ActiveX对象; 而Mozilla、Netscape 7、Opera和Safari 1.2及以上版本使用XMLHttpRequest对象。另一个区别在于创建对象的方式: Opera、Mozilla、Netscape和Safari允许只要调用该对象的构造函数,但Windows IE需要将对象名称传递到ActiveX构造函数中。下面这个示例表明了如何编写代码来确定使用哪个对象、如何创建对象:

if(window.XMLHttpRequest)
{ request = new XMLHttpRequest();}
else if(window.ActiveXObject)
{ request = new ActiveXObject("MSXML2.XMLHTTP");}
● 发出请求
请求对象创建好后,就可以准备向服务器发出请求了。为事件处理器创建引用,以侦听onreadystatechange。随后,事件处理器方法在状态发生变化时会做出响应。一旦完成了请求,就可以创建这个方法。打开连接,GET或者POST定制的URL——这里是content.xml,然后设置布尔值,定义是否希望调用异步调用。

现在可以发出请求了。示例中使用了null,因为我们用的是GET; 想用POST,则需要用这个方法发送一个查询字符串:
request.onreadystatechange = onResponse;
request.open("GET". url, true);
request.send(null);
● 定制加载和错误处理消息
为onreadystatechange方法创建的事件处理器是专门负责加载及错误处理的地方。在示例中,为所有加载状态代码提供了反馈,还为最经常发生的错误处理状态代码提供了一些基本反馈。为了显示请求对象的当前状态,readyState属性包括表3中显示的一些值。



W3C详细列出了HTTP状态代码的定义。我选择了其中两个状态代码: 200,请求已成功; 404,服务器没有找到与请求文件相匹配的任何东西。

最后,我们检查了会生成错误并提供一般错误信息的其他状态代码。下面是一个代码示例,可以用该代码处理这些情况。不过要注意,这里把目标定于我们在HTML文件的主体中创建的div ID,并且使用innerHTML方法,添加了装载以及/或者错误消息——该方法设置了div对象的开始和结束标记之间的HTML:

if(obj.readyState == 0)
{ document.getElementById('copy').innerHTML = "Sending Request...";}

if(obj.readyState == 1)
{ document.getElementById('copy').innerHTML = "Loading Response...";}

if(obj.readyState == 2)
{ document.getElementById('copy').innerHTML = "Response Loaded...";}

if(obj.readyState == 3)
{ document.getElementById('copy').innerHTML = "Response Ready...";}

if(obj.readyState == 4){
if(obj.status == 200){ return true; }
else if(obj.status == 404)
{
// 把定制消息添加到另一个页面上,或者把用户重定向到另一个页面上
document.getElementById('copy').innerHTML = "File not found";
}
else
{document.getElementById('copy').innerHTML = "There was a problem retrieving the XML."; }

}
如果状况代码为200,这意味着请求成功,响应可以随时准备解析了。
● 解析响应
准备好解析请求对象的响应时,真正的工作开始了。这时候就可以真正开始处理所请求的数据了。为了便于在开发过程中进行测试,responseText和responseXML属性可用来显示来自响应的原始数据。为了开始访问XML响应中的节点,先从已创建的请求对象入手,定位responseXML属性,检索来自响应的XML。然后定位documentElement,它会检索XML响应的根节点的引用。

var response = request.responseXML.documentElement;
已经有了响应根节点的引用,这时你可以使用getElementsByTagName(),按节点名称来检索childNodes。下面一行用头的nodeName来定位childNode:

response.getElementsByTagName('header')[0].firstChild.data;
使用firstChild.data就可以访问元素里面的文本:
response.getElementsByTagName('header')[0].firstChild.data;
以下是如何编写代码的完整示例:
var response = request.responseXML.documentElement;
var header = response.getElementsByTagName('header')[0].firstChild.data;

document.getElementById('copy').innerHTML = header; (沈建苗编译)
虽然AJAX允许我们以新颖的方式与网页进行交互,可是作为开发人员,我们需要牢记产品并不单单涉及技术,还涉及用户以及他们如何与产品进行交互。要是没有用户,我们构建的项目将毫无用处。如果时时考虑到这条准则,我们就能评估使用什么技术、何时使用它们,从而创建有助于所有使用者的应用程序。

(计算机世界报 2006年08月07日 第30期 B31、B32)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: