1、简介
多数 Web 应用程序都使用请求/响应模型从服务器上获得完整的 HTML 页面。常常是点击一个按钮,等待服务器响应,再点击另一个按钮,然后再等待,这样一个反复的过程。有了 Ajax 和 XMLHttpRequest 对象,就可以使用不必让用户等待服务器响应的请求/响应模型了。
2、XMLHttpRequest对象
该对象的几个 方法和属性。
-
open()
:建立到服务器的新请求。 -
send()
:向服务器发送请求。 -
abort()
:退出当前请求。 -
readyState
:提供当前 HTML 的就绪状态。 -
responseText
:服务器返回的请求响应文本。
<divre class="java" name="code" mce_tmp="1"><script language="javascript" type="text/javascript"> var request = new XMLHttpRequest(); </script> </divre>
<divre mce_tmp="1"></divre>
创建一个对象很容易,但是在实际上各种事情都可能出错,而上面的代码没有提供任何错误处理。较好的办法是创建该对象,并在出现问题时优雅地退出。比如,任何较早的浏览器都不支持 XMLHttpRequest
,这就需要让我们知道有些地方出了问题。
<divre class="java" name="code" mce_tmp="1"><script language="javascript" type="text/javascript"> var request = false; try { request = new XMLHttpRequest(); } catch (failed) { request = false; } if (!request) alert("Error initializing XMLHttpRequest!"); </script> </divre>
<divre mce_tmp="1"></divre>
- 创建一个新变量
request
并赋值 false。后面将使用 false 作为判定条件,它表示还没有创建XMLHttpRequest
对象。 - 增加 try/catch 块:
- 尝试创建
XMLHttpRequest
对象。 - 如果失败(
catch (failed)
)则保证request
的值仍然为 false。
- 尝试创建
- 检查
request
是否仍为 false(如果一切正常就不会是 false)。 - 如果出现问题(
request
是 false)则使用 JavaScript 警告通知用户出现了问题。
代码非常简单,对大多数 JavaScript 和 Web 开发人员来说,真正理解它要比读写代码花更长的时间。现在已经得到了一段带有错误检查的 XMLHttpRequest
对象创建代码,还可以告诉您哪儿出了问题。
3、用 XMLHttpRequest 发送请求
使用沙箱安全模型
主要指的是跨域脚本调用的问题。比如我们存在在www.cnblogs.com中的脚本如果想访问www.163.com 脚本是违反沙箱安全模型的。结果肯定会出错。只能是www.cnblogs.com 调用www.cnblogs.com中的脚本代码。
打开请求
XMLHttpRequest
对象的 open()
方法来完成。该方法有五个参数:
- request-type:发送请求的类型。典型的值是
GET
或POST
,但也可以发送HEAD
请求。 - url:要连接的 URL。
- asynch:如果希望使用异步连接则为 true,否则为 false。该参数是可选的,默认为 true。
- username:如果需要身份验证,则可以在此指定用户名。该可选参数没有默认值。
- password:如果需要身份验证,则可以在此指定口令。该可选参数没有默认值。
通常使用其中的前三个参数。事实上,即使需要异步连接,也应该指定第三个参数为 “true”。这是默认值,但坚持明确指定请求是异步的还是同步的更容易理解。
异步请求
异步请求不 等待服务器响应。发送请求后应用程序继续运行。用户仍然可以在 Web 表单中输入数据,甚至离开表单。没有旋转的皮球或者沙漏,应用程序也没有明显的冻结。服务器悄悄地响应请求,完成后告诉原来的请求者工作已经结束(具体的办法很快就会看到)。结果是,应用程序感觉不 那么迟钝或者缓慢,而是响应迅速、交互性强,感觉快多了。这仅仅是 Web 2.0 的一部分,但它是很重要的一部分。所有老套的 GUI 组件和 Web 设计范型都不能克服缓慢、同步的请求/响应模型。
<divre class="java" name="code" mce_tmp="1">function getCustomerInfo() { var phone = document.getElementById("phone").value; var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone); request.open("GET", url, true); } </divre>
<divre mce_tmp="1"></divre>
发送请求
虽然可以使用 send()
发送数据,但也能通过 URL 本身发送数据。事实上,GET
请求(在典型的 Ajax 应用中大约占 80%)中,用 URL 发送数据要容易得多。如果需要发送安全信息或 XML,可能要考虑使用 send()
发送内容。如果不需要通过 send()
传递数据,则只要传递 null
作为该方法的参数即可。
<divre class="java" name="code" mce_tmp="1">function getCustomerInfo() { var phone = document.getElementById("phone").value; var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone); request.open("GET", url, true); request.send(null); } </divre>
指定回调方法
建立其请求然后发出请求。此外,因为是异步请求,所以 JavaScript 方法不会等待服务器。因此代码将继续执行,就是说,将退出该方法而把控制返回给表单。用户可以继续输入信息,应用程序不会等待服务器。
这就提出了一个有趣的问题:服务器完成了请求之后会发生什么?答案是什么也不发生,至少对现在的代码而言如此!显然这样不行,因此服务器在完成通过 XMLHttpRequest
发送给它的请求处理之后需要某种指示说明怎么做。答案就在于 XMLHttpRequest
的一个简单属性 onreadystatechange
。
该属性允许指定一个回调函数。回调允许服务器反向调用 Web 页面中的代码。它也给了服务器一定程度的控制权,当服务器完成请求之后,会查看 XMLHttpRequest
对象,特别是 onreadystatechange
属性。然后调用该属性指定的任何方法。之所以称为回调是因为服务器向网页发起调用,无论网页本身在做什么。比方说,可能在用户坐在椅子上手没有碰键盘的时候调用该方法,但是也可能在用户输入、移动鼠标、滚动屏幕或者点击按钮时调用该方法。它并不关心用户在做什么。
这就是称之为异步的原因:用户在一层上操作表单,而在另一层上服务器响应请求并触发 onreadystatechange
属性指定的回调方法。
<divre class="java" name="code" mce_tmp="1">function getCustomerInfo() { var phone = document.getElementById("phone").value; var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone); request.open("GET", url, true); <font style="BACKGROUND-COLOR: #ff00ff" mce_style="background-color: #ff00ff;">request.onreadystatechange</font> = updatePage; request.send(null); } </divre>
现在我们已经看到如何告诉服务器完成后应该做什么:将 XMLHttpRequest
对象的 onreadystatechange
属性设置为要运行的函数名。这样,当服务器处理完请求后就会自动调用该函数。也不需要担心该函数的任何参数。
<script language="javascript" type="text/javascript"> var request = false; try { request = new XMLHttpRequest(); } catch (trymicrosoft) { try { request = new ActiveXObject("Msxml2.XMLHTTP"); } catch (othermicrosoft) { try { request = new ActiveXObject("Microsoft.XMLHTTP"); } catch (failed) { request = false; } } } if (!request) alert("Error initializing XMLHttpRequest!"); function getCustomerInfo() { var phone = document.getElementById("phone").value; var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone); request.open("GET", url, true); request.onreadystatechange = updatePage; request.send(null); } function updatePage() { alert("Server is done!"); } </script> |
在 Ajax 应用程序中需要了解五种就绪状态:
- 0:请求没有发出(在调用
open()
之前)。 - 1:请求已经建立但还没有发出(调用
send()
之前)。 - 2:请求已经发出正在处理之中(这里通常可以从响应得到内容头部)。
- 3:请求已经处理,响应中通常有部分数据可用,但是服务器还没有完成响应。
- 4:响应已完成,可以访问服务器响应并使用它。
function updatePage() { alert("Server is done!"); } |
但是还有一个问题 —— 如果服务器响应请求并完成了处理但是报告了一个错误怎么办?因此除了就绪状态外,还需要检查 HTTP 状态。我们期望的状态码是 200,它表示一切顺利。如果就绪状态是 4 而且状态码是 200,就可以处理服务器的数据了,而且这些数据应该就是要求的数据。
function updatePage() { if (request.readyState == 4) if (request.status == 200) alert("Server is done!"); } |
为了增加更健壮的错误处理并尽量避免过于复杂,可以增加一两个状态码检查。
function updatePage() { if (request.readyState == 4) { if (request.status == 200) { var response = request.responseText.split("|"); document.getElementById("order").value = response[0]; document.getElementById("address").innerHTML = response[1].replace(/\n/g, " |