要真正实现这种绚丽的奇迹,必须很是熟悉一个 JavaScript 对象,即 XMLHttpRequest。javascript
下面给出将要用于该对象的不多的几个 方法和属性。php
·open():创建到服务器的新请求。
·send():向服务器发送请求。
·abort():退出当前请求。
·readyState:提供当前 HTML 的就绪状态。
·responseText:服务器返回的请求响应文本。 java
1. 建立新的 XMLHttpRequest 对象程序员
<script language="javascript" type="text/javascript">
var request = new XMLHttpRequest();
</script>正则表达式
在 JavaScript 中用 var 建立一个变量,给它一个名字(如 “request”),而后赋给它一个新的 XMLHttpRequest 实例。此后就能够在函数中使用该对象了。编程
错误处理数组
在实际上各类事情均可能出错,而上面的代码没有提供任何错误处理。较好的办法是建立该对象,并在出现问题时优雅地退出。浏览器
2.建立具备错误处理能力的 XMLHttpRequest安全
<script language="javascript" type="text/javascript"> var request = false; try { request = new XMLHttpRequest(); } catch (failed) { request = false; } if (!request) alert("Error initializing XMLHttpRequest!"); </script>
一、建立一个新变量 request 并赋值 false。后面将使用 false 做为断定条件,它表示尚未建立 XMLHttpRequest 对象。
二、增长 try/catch 块:
1)尝试建立 XMLHttpRequest 对象。
2)若是失败(catch (failed))则保证 request 的值仍然为 false。
三、检查 request 是否仍为 false(若是一切正常就不会是 false)。
四、若是出现问题(request 是 false)则使用 JavaScript 警告通知用户出现了问题。 服务器
增长对 Microsoft 浏览器IE6(如下)的支持
<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!"); </script>
一、建立一个新变量 request 并赋值 false。使用 false 做为判断条件,它表示尚未建立 XMLHttpRequest 对象。
二、增长 try/catch 块:
1)尝试建立 XMLHttpRequest 对象。
2)若是失败(catch (trymicrosoft)):
1>尝试使用较新版本的 Microsoft 浏览器建立 Microsoft 兼容的对象(Msxml2.XMLHTTP)。
2> 若是失败(catch (othermicrosoft))尝试使用较老版本的 Microsoft 浏览器建立 Microsoft 兼容的对象(Microsoft.XMLHTTP)。
2)若是失败(catch (failed))则保证 request 的值仍然为 false。
三、检查 request 是否仍然为 false(若是一切顺利就不会是 false)。
四、若是出现问题(request 是 false)则使用 JavaScript 警告通知用户出现了问题。
全部这些代码都直接嵌套在 script 标记中。像这种不放到方法或函数体中的 JavaScript 代码称为静态 JavaScript。就是说代码是在页面显示给用户以前的某个时候运行。(虽然根据规范不能彻底精确地 知道这些代码什么时候运行对浏览器有什么影响,可是能够保证这些代码在用户可以与页面交互以前运行。)这也是多数 Ajax 程序员建立 XMLHttpRequest 对象的通常方式。
将 XMLHttpRequest 建立代码移动到方法中
<script language="javascript" type="text/javascript"> var request; function createRequest() { 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!"); } </script>
使用 XMLHttpRequest 的建立方法
<script language="javascript" type="text/javascript"> var request; function createRequest() { 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() { createRequest(); // Do something with the request variable } </script>
此代码唯一的问题是推迟了错误通知,这也是多数 Ajax 程序员不采用这一方法的缘由。假设一个复杂的表单有 10 或 15 个字段、选择框等,当用户在第 14 个字段(按照表单顺序从上到下)输入文本时要激活某些 Ajax 代码。这时候运行 getCustomerInfo() 尝试建立一个 XMLHttpRequest 对象,但(对于本例来讲)失败了。而后向用户显示一条警告,明确地告诉他们不能使用该应用程序。但用户已经花费了不少时间在表单中输入数据!这是很是使人讨厌的,而讨厌显然不会吸引用户再次访问您的网站。
用 XMLHttpRequest 发送请求
获得请求对象以后就能够进入请求/响应循环了。记住,XMLHttpRequest 唯一的目的是让您发送请求和接收响应。其余一切都是 JavaScript、CSS 或页面中其余代码的工做:改变用户界面、切换图像、解释服务器返回的数据。准备好 XMLHttpRequest 以后,就能够向服务器发送请求了。
Ajax 采用一种沙箱安全模型。所以,Ajax 代码(具体来讲就是 XMLHttpRequest 对象)只能对所在的同一个域发送请求。
设置服务器 URL
创建请求 URL
<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); } </script>
Break Neck Pizza 表单
<body> <p><img src="breakneck-logo_4c.gif" alt="Break Neck Pizza" /></p> <form action="POST"> <p>Enter your phone number: <input type="text" size="14" name="phone" id="phone" onChange="getCustomerInfo();" /> </p> <p>Your order will be delivered to:</p> <div id="address"></div> <p>Type your order in here:</p> <p><textarea name="order" rows="6" cols="50" id="order"></textarea></p> <p><input type="submit" value="Order Pizza" id="submit" /></p> </form> </body>
当用户输入电话号码或者改变电话号码时,将触发getCustomerInfo() 方法。该方法取得电话号码并构造存储在 url 变量中的 URL 字符串。记住,因为 Ajax 代码是沙箱型的,于是只能链接到同一个域,实际上 URL 中不须要域名。该例中的脚本名为 /cgi-local/lookupCustomer.php。最后,电话号码做为 GET 参数附加到该脚本中:"phone=" + escape(phone)。
若是之前没用见过 escape() 方法,它用于转义不能用明文正确发送的任何字符。好比,电话号码中的空格将被转换成字符 %20,从而可以在 URL 中传递这些字符。
能够根据须要添加任意多个参数。好比,若是须要增长另外一个参数,只须要将其附加到 URL 中并用 “与”(&)字符分开 [第一个参数用问号(?)和脚本名分开]。
打开请求
有了要链接的 URL 后就能够配置请求了。能够用 XMLHttpRequest 对象的 open() 方法来完成。该方法有五个参数:
request-type:发送请求的类型。典型的值是 GET 或 POST,但也能够发送 HEAD 请求。
url:要链接的 URL。
asynch:若是但愿使用异步链接则为 true,不然为 false。该参数是可选的,默认为 true。
username:若是须要身份验证,则能够在此指定用户名。该可选参数没有默认值。
password:若是须要身份验证,则能够在此指定口令。该可选参数没有默认值。
open() 是打开吗?
Internet 开发人员对 open() 方法到底作什么没有达成一致。但它实际上并非 打开一个请求。若是监控 XHTML/Ajax 页面及其链接脚本之间的网络和数据传递,当调用 open() 方法时将看不到任何通讯。
一般使用其中的前三个参数。事实上,即便须要异步链接,也应该指定第三个参数为 “true”。这是默认值,但坚持明确指定请求是异步的仍是同步的更容易理解。
function getCustomerInfo() { var phone = document.getElementById("phone").value; var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone); request.open("GET", url, true); }
一旦用 open() 配置好以后,就能够发送请求了。幸运的是,发送请求的方法的名称要比 open() 适当,它就是 send()。
send() 只有一个参数,就是要发送的内容。可是在考虑这个方法以前,回想一下前面已经经过 URL 自己发送过数据了:
var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);
虽然可使用 send() 发送数据,但也能经过 URL 自己发送数据。事实上,GET 请求(在典型的 Ajax 应用中大约占 80%)中,用 URL 发送数据要容易得多。若是须要发送安全信息或 XML,可能要考虑使用 send() 发送内容
。若是不须要经过 send() 传递数据,则只要传递 null 做为该方法的参数便可。
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); }
XMLHttpRequest 的一个简单属性 onreadystatechange。
由于是异步请求,因此 JavaScript 方法(例子中的 getCustomerInfo())不会等待服务器。所以代码将继续执行,就是说,将退出该方法而把控制返回给表单。用户能够继续输入信息,应用程序不会等待服务器。
这就提出了一个有趣的问题:服务器完成了请求以后会发生什么?答案是什么也不发生,至少对如今的代码而言如此!显然这样不行,所以服务器在完成经过 XMLHttpRequest 发送给它的请求处理以后须要某种指示说明怎么作。
在 JavaScript 中引用函数:
JavaScript 是一种弱类型的语言,能够用变量引用任何东西。所以若是声明了一个函数 updatePage(),JavaScript 也将该函数名看做是一个变量。换句话说,可用变量名 updatePage 在代码中引用函数。
设置回调方法
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); }
须要特别注意的是该属性在代码中设置的位置 —— 它是在调用 send() 以前 设置的。发送请求以前必须设置该属性,这样服务器在回答完成请求以后才能查看该属性。如今剩下的就只有编写 updatePage() 方法了
处理服务器响应
用户高兴地使用 Web 表单(同时服务器在处理请求),而如今服务器完成了请求处理。服务器查看 onreadystatechange 属性肯定要调用的方法。除此之外,能够将您的应用程序看做其余应用程序同样,不管是否异步。换句话说,不必定要采起特殊的动做编写响应服务器的方法,只须要改变表单,让用户访问另外一个 URL 或者作响应服务器须要的任何事情。
如今咱们已经看到如何告诉服务器完成后应该作什么:将 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>
它仅仅发出一些简单的警告,告诉您服务器何时完成了任务。
根据浏览器的不一样,在表单中止弹出警告以前会看到两次、三次甚至四次警告。这是怎么回事呢?原来咱们尚未考虑 HTTP 就绪状态,这是请求/响应循环中的一个重要部分。
HTTP 就绪状态
服务器在完成请求以后会在 XMLHttpRequest 的 onreadystatechange 属性中查找要调用的方法。这是真的,但还不完整。事实上,每当 HTTP 就绪状态改变时它都会调用该方法。
在 Ajax 应用程序中须要了解五种就绪状态:
·0:请求没有发出(在调用 open() 以前)。
·1:请求已经创建但尚未发出(调用 send() 以前)。
·2:请求已经发出正在处理之中(这里一般能够从响应获得内容头部)。
·3:请求已经处理,响应中一般有部分数据可用,可是服务器尚未完成响应。
·4:响应已完成,能够访问服务器响应并使用它。
对于 Ajax 编程,须要直接处理的唯一状态就是就绪状态 4,它表示服务器响应已经完成,能够安全地使用响应数据了。
检查就绪状态
function updatePage() { if (request.readyState == 4) alert("Server is done!"); }
修改后就能够保证服务器的处理已经完成。
HTTP 状态码
还有一个问题 —— 若是服务器响应请求并完成了处理可是报告了一个错误怎么办?要知道,服务器端代码应该明白它是由 Ajax、JSP、普通 HTML 表单或其余类型的代码调用的,但只能使用传统的 Web 专用方法报告信息。而在 Web 世界中,HTTP 代码能够处理请求中可能发生的各类问题。
您确定遇到过输入了错误的 URL 请求而获得 404 错误码的情形,它表示该页面不存在。这仅仅是 HTTP 请求可以收到的众多错误码中的一种(完整的状态码列表请参阅 参考资料 中的连接)。表示所访问数据受到保护或者禁止访问的 403 和 401 也很常见。不管哪一种状况,这些错误码都是从完成的响应 获得的。换句话说,服务器履行了请求(即 HTTP 就绪状态是 4)可是没有返回客户机预期的数据。
所以除了就绪状态外,还须要检查 HTTP 状态。咱们指望的状态码是 200,它表示一切顺利。若是就绪状态是 4 并且状态码是 200,就能够处理服务器的数据了,并且这些数据应该就是要求的数据(而不是错误或者其余有问题的信息)。所以还要在回调方法中增长状态检查
检查 HTTP 状态码
function updatePage() { if (request.readyState == 4) if (request.status == 200) alert("Server is done!"); }
为了增长更健壮的错误处理并尽可能避免过于复杂,能够增长一两个状态码检查
function updatePage() { if (request.readyState == 4) if (request.status == 200) alert("Server is done!"); else if (request.status == 404) alert("Request URL does not exist"); else alert("Error: status code is " + request.status); }
如今能够确保请求已经处理完成(经过就绪状态),服务器给出了正常的响应(经过状态码),最后咱们能够处理服务器返回的数据了。返回的数据保存在 XMLHttpRequest 对象的 responseText 属性中。
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, ""); } else alert("status is " + request.status); } }
获得 responseText 并使用 JavaScript split() 方法从管道符分开。获得的数组放到 response 中。
获得的数组放到 response 中。数组中的第一个值 —— 上一个订单 —— 用 response[0] 访问,被设置为 ID 为 “order” 的字段的值。第二个值 response[1],即客户地址,则须要更多一点处理。由于地址中的行用通常的行分隔符(“\n”字符)分隔,代码中须要用 XHTML 风格的行分隔符 <br /> 来代替。替换过程使用 replace() 函数和正则表达式完成。最后,修改后的文本做为 HTML 表单 div 中的内部 HTML。结果就是表单忽然用客户信息更新了
XMLHttpRequest 的另外一个重要属性 responseXML。若是服务器选择使用 XML 响应则该属性包含(也许您已经猜到)XML 响应。处理 XML 响应和处理普通文本有很大不一样,涉及到解析、文档对象模型(DOM)和其余一些问题。