Ajax基础
参考:http://www.ibm.com/developerworks/cn/web/wa-ajaxintro/
Ajax的运行机制
在一般的 Web 应用程序中,用户填写表单字段并单击 Submit 按钮。然后整个表单发送到服务器,服务器将它转发给处理表单的脚本(通常是 PHP 或 Java,也可能是 CGI 进程或者类似的东西),脚本执行完成后再发送回全新的页面。该页面可能是带有已经填充某些数据的新表单的 HTML,也可能是确认页面,或者是具有根据原来表单中输入数据选择的某些选项的页面。当然,在服务器上的脚本或程序处理和返回新表单时用户必须等待。屏幕变成一片空白,等到服务器返回数据后再重新绘制。这就是交互性差的原因,用户得不到立即反馈,因此感觉不同于桌面应用程序。
Ajax 基本上就是把 JavaScript 技术和 XMLHttpRequest 对象放在 Web 表单和服务器之间。当用户填写表单时,数据发送给一些 JavaScript 代码而不是 直接发送给服务器。相反,JavaScript 代码捕获表单数据并向服务器发送请求。同时用户屏幕上的表单也不会闪烁、消失或延迟。换句话说,JavaScript 代码在幕后发送请求,用户甚至不知道请求的发出。更好的是,请求是异步发送的,就是说 JavaScript 代码(和用户)不用等待服务器的响应。因此用户可以继续输入数据、滚动屏幕和使用应用程序。
然后,服务器将数据返回 JavaScript 代码(仍然在 Web 表单中),后者决定如何处理这些数据。它可以迅速更新表单数据,让人感觉应用程序是立即完成的,表单没有提交或刷新而用户得到了新数据。JavaScript 代码甚至可以对收到的数据执行某种计算,再发送另一个请求,完全不需要用户干预!这就是XMLHttpRequest 的强大之处。它可以根据需要自行与服务器进行交互,用户甚至可以完全不知道幕后发生的一切。结果就是类似于桌面应用程序的动态、快速响应、高交互性的体验,但是背后又拥有互联网的全部强大力量。
创建XMLHttpRequest 对象
open():建立到服务器的新请求。
send():向服务器发送请求。
abort():退出当前请求。
readyState:提供当前 HTML 的就绪状态。
responseText: 服务器返回的请求响应文本。
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
var request = false;
try {
//new XMLHttpRequest
request = new XMLHttpRequest();
} catch (trymicrosoft) {//用较新版IE创建Microsoft兼容的对象
try {
request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (othermicrosoft) {//用旧版IE创建Microsoft兼容的对象
try {
request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (failed) {
request = false;
}
}
}
if (!request)
alert("XMLHttpRequest创建失败!");
Ajax 世界中的请求/响应
发出请求:首先需要一个 Web 页面能够调用的JavaScript 方法(比如当用户输入文本或者从菜单中选择一项时)。接 下来就是在所有 Ajax 应用程序中基本都雷同的流程:
1) 从 Web 表单中获取需要的数据。
2) 建立要连接的 URL。
3) 打开到服务器的连接。
4) 设置服务器在完成后要运行的函数。
5) 发送请求。
处理响应 :现在要面对服务器的响应了。现在只要知道两点:
1) 什么也不要做,直到 xmlHttp.readyState 属性的值等于 4。
2) 服务器将把响应填充到 xmlHttp.responseText 属性中。
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
function getCustomerInfo() {
//建立请求URL
var phone = document.getElementById("phone").value;
var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);
//打开请求
//使用异步连接则为 true,否则为 false
request.open("GET", url, true);
//指定回调方法。回调允许服务器反向调用Web页面中的代码。它也给了服务器一定程度的控制权,
//服务器完成请求后,查看XMLHttpRequest对象,然后调用onreadystatechange属性指定的方法。
request.onreadystatechange = updatePage;
//发送请求
//虽然可以使用send()发送数据,但也能通过URL本身发送数据。
//GET请求中,用URL发送数据要容易得多.如果需要发送安全信息或 XML,可能要使用send()发送内容。
//如果不需要通过 send()传递数据,则只要传递 null 作为该方法的参数即可
request.send(null);
}
//回调方法
function updatePage() {
if (request.readyState == 4) //HTTP就绪状态4: 表示服务器响应已经完成
if (request.status == 200) //HTTP状态码200: 表示一切顺利
alert("Server is done!");
else if (request.status == 404)
alert("您所请求的网页不存在");
else
alert("错误:状态码为" + request.status);
}
有用的 HEAD 请求
您会发现 HEAD 请求非常有用的一个领域是用来查看内容的长度或内容的类型。这样可以确定是否需要发回大量数据来处理请求,和服务器是否试图返回二进制数据,而不是 HTML、文本或 XML(在 JavaScript 中,这 3 种类型的数据都比二进制数据更容易处理)。
在这些情况中,您只使用了适当的头名,并将其传递给 XMLHttpRequest 对象的 getResponseHeader() 方法。因此要获取响应的长度,只需要调用 request.getResponseHeader("Content-Length");。要获取内容类型,请使用 request.getResponseHeader("Content-Type");。
在很多应用程序中,生成 HEAD 请求并没有增加任何功能,甚至可能会导致请求速度变慢(通过强制生成一个 HEAD 请求来获取有关响应的数据,然后在使用一个 GET 或 POST 请求来真正获取响应)。然而,在出现您不确定有关脚本或服务器端组件的情况时,使用 HEAD 请求可以获取一些基本的数据,而不需要对响应数据真正进行处理,也不需要大量的带宽来发送响应。
增加这种生成 HEAD 请求的能力,检查某个 URL 是否存在,以及确认某个文件是否被修改过,这样就可以确保用户可以获得有效的页面,用户所看到的信息都是最新的.
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
//使用 Ajax 生成一个 HEAD 请求
function getSalesData() {
createRequest();
var url = "/boards/servlet/UpdateBoardSales";
request.open("HEAD", url, true);
request.onreadystatechange = updatePage;
request.send(null);
}
// 输出从 HEAD 请求中获得的响应头的内容
function updatePage() {
if (request.readyState == 4) {
alert(request.getAllResponseHeaders());
}
}
使用 XML
在异步应用程序中 XML 有两种基本的用法:
A:以 XML 格式从网页向服务器发送请求
B:以 XML 格式在网页中从服务器接收请求
其中第一种用法,即用 XML 发送请求,需要将请求的格式设置为 XML,可以使用 API 来完成,也可以与文本连成字符串,然后将结果发送到服务器。按照这种思路,主要的任务就是通过既符合 XML 规则又能被服务器理解的方式构造请求。因此这里的关键实际上是 XML 格式,得到需要发送的数据之后,只需要用 XML 语法将其包装起来。
第二种用法,即用 XML 接收请求,需要从服务器上接收响应,然后从 XML 提取数据(同样,可以用 API 或者采用蛮力方法)。这种情况下,关键在于来自服务器的数据。
A:从客户机到服务器的 XML
在网络上传输 XML 之前,需要保证服务器以及发送数据的脚本能够接受 XML。现在对很多人来说这么强调似乎有点多余,认为这是理所当然的,但是很多新手往往认为只要通过网络发送 XML,就能够被正确地接收和解释。
实际上,需要两个步骤来保证发送的 XML 的数据能够被正确地接收:
1.保证向其发送 XML 的脚本能够接受 XML 数据格式。
2.保证脚本认可发送数据所采用的特定 XML 格式和结构。
注意:在向服务器的请求中尽量不要使用XML .因为通常XML总会占用更多的空间,速度也更慢,XML没有为请求增加任何东西,难于操作、理解和维护。因此除非和只接受XML的脚本打交道,在请求中最好使用普通文本。
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
function callServer() {
// 从页面获取信息
var firstName = document.getElementById("firstName").value;
var lastName = document.getElementById("lastName").value;
var street = document.getElementById("street").value;
var city = document.getElementById("city").value;
var state = document.getElementById("state").value;
var zipCode = document.getElementById("zipCode").value;
//按照指定的xml格式组织信息。
//必须手工创建 XML。使用 DOM 不是一种好的选择,因为没有简单
//易行的办法将 DOM 对象转化成在请求中发送的字符串。
//缺点:难以理解和维护
var xmlString = "<profile>" +
" <firstName>" + escape(firstName) + "</firstName>" +
" <lastName>" + escape(lastName) + "</lastName>" +
" <street>" + escape(street) + "</street>" +
" <city>" + escape(city) + "</city>" +
" <state>" + escape(state) + "</state>" +
" <zip-code>" + escape(zipCode) + "</zip-code>" +
"</profile>";
var url = "/scripts/saveAddress.php";
//有些浏览器限制了GET请求字符串的长度,对于XML最好使用POST请求
xmlHttp.open("POST", url, true);
//告诉服务器要发送的是XML而不是一般的名/值对
xmlHttp.setRequestHeader("Content-Type", "text/xml");
xmlHttp.onreadystatechange = confirmUpdate;
//将XML字符串作为参数发出
xmlHttp.send(xmlString);
}
B:以 XML 格式在网页中从服务器接收请求
在您发送名称/值对时,Web 浏览器会发送请求,平台会响应该请求,并承载一个服务器程序,配合它将那些名称/值对转换成服务器程序可以轻松处理的数据。实际上,每一种服务器端技术 —— 从 Java? servlet 到 PHP、再到 Perl、Ruby on Rails —— 都允许您调用多种方法来根据名称获取值。如果服务器使用字符串 name=jennifer&job=president 应答一个应用程序,客户机没有任何标准化的简便方法来将每个对拆分成名称和值。您必须手动解析所返回的数据。如果服务器返回一个由名称/值对构成的响应,这样的响应的解释难度与使用分号、竖线或其他任何非标准格式化字符相同。
向客户机发送数据时,名称/值对是非常好的选择,因为服务器和服务器端语言可以轻松解释名称/值对;向客户机返回数据时使用 XML 也是如此。您可以将 XML 作为纯文本处理,并以这种方式获取其值。因此,有几种方法可从服务器获得 XML 响应,并使用较为标准的代码提取数据,在客户机中使用这些数据。还有一个额外的好处,XML 非常易于理解。
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
//作为格式化为XML的纯文本处理
function updatePage() {
if (request.readyState == 4) {
if (request.status == 200) {
var response = request.responseText;
// response has the XML response from the server
alert(response);
}
}
}
//作为一个XML文档,由一个DOM Document对象表示
function updatePage() {
if (request.readyState == 4) {
if (request.status == 200) {
var xmlDoc = request.responseXML;
var showElements = xmlDoc.getElementsByTagName("show");
for (var x=0; x<showElements.length; x++) {
//We know that the first child of show is title,and the second is rating
var title = showElements[x].childNodes[0].value;
var rating = showElements[x].childNodes[1].value;
// Now do whatever you want with the show title and ratings
}
}
}
}
使用JSON进行数据传输
JSON 可以将 JavaScript 对象中表示的一组数据转换为字符串,然后就可以在函数之间轻松地传递这个字符串,或者在异步应用程序中将字符串从 Web 客户机传递给服务器端程序。这个字符串看起来有点儿古怪(稍后会看到几个示例),但是 JavaScript 很容易解释它,而且 JSON 可以表示比名称/值对更复杂的结构。例如,可以表示数组和复杂的对象,而不仅仅是键和值的简单列表。
当需要表示一组值时,JSON 不但能够提高可读性,而且可以减少复杂性。例如,假设您希望表示一个人名列表。在 XML 中,需要许多开始标记和结束标记;如果使用典型的名称/值对(就像在本系列前面文章中看到的那种名称/值对),那么必须建立一种专有的数据格式,或者将键名称修改为 person1-firstName 这样的形式。
在这个示例中,只有一个名为 people 的变量,值是包含三个条目的数组,每个条目是一个人的记录,其中包含名、姓和电子邮件地址。上面的示例演示如何用括号将记录组合成一个值。当然,可以使用相同的语法表示多个值(每个值包含多个记录).这里最值得注意的是,能够表示多个值,每个值进而包含多个值。但是还应该注意,在不同的主条目(programmers、authors 和 musicians)之间,记录中实际的名称/值对可以不一样。JSON 是完全动态的,允许在 JSON 结构的中间改变表示数据的方式。掌握了 JSON 格式之后,在 JavaScript 中使用它就很简单了。JSON 是 JavaScript 原生格式,这意味着在 JavaScript 中处理 JSON 数据不需要任何特殊的 API 或工具包。
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
//生成JSON对象
var people =
{ "programmers": [
{ "firstName": "Brett", "lastName":"McLaughlin", "email": "brett@nance.com" },
{ "firstName": "Jason", "lastName":"Hunter", "email": "jason@servlets.com" },
{ "firstName": "Elliotte", "lastName":"Harold", "email": "elharo@macfaq.com" }
],
"authors": [
{ "firstName": "Isaac", "lastName": "Asimov", "genre": "science fiction" },
{ "firstName": "Tad", "lastName": "Williams", "genre": "fantasy" },
{ "firstName": "Frank", "lastName": "Peretti", "genre": "christian fiction" }
],
"musicians": [
{ "firstName": "Eric", "lastName": "Clapton", "instrument": "guitar" },
{ "firstName": "Sergei", "lastName": "Rachmaninoff", "instrument": "piano" }
]
}
//访问JSON对象的属性
people.authors[1].genre // Value is "fantasy"
people.musicians[3].lastName // Undefined. This refers to the fourth entry,
people.programmers.[2].firstName // Value is "Elliotte"
//修改JSON对象的属性
people.musicians[1].lastName = "Rachmaninov";
//将JSON对象转化为字符串,就可以在任何地方使用
String newJSONtext = people.toJSONString();
现在就获得了一个可以在任何地方使用的文本字符串,例如,可以将它用作 Ajax 应用程序中的请求字符串。
可以将任何 JavaScript 对象转换为 JSON 文本。并非只能处理原来用 JSON 字符串赋值的变量。为了对名为 myObject 的对象进行转换,只需执行相同形式的命令:
String myObjectInJSON = myObject.toJSONString();
最终结论是,如果要处理大量 JavaScript 对象,那么 JSON 几乎肯定是一个好选择,这样就可以轻松地将数据转换为可以在请求中发送给服务器端程序的格式。