异步传输ajax
什么是异步传输,首先让我们看看传统的数据加载方式“同步传输”,传统的页面加载一般是从上开始往下加载的,当需要加载js的时候,是阻塞加载,当引用了js的时候,浏览器发送一个js request就会一直等待该request的返回。
因此这样写会提示错误的:
1 <html> 2 <head> 3 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 4 <title>up</title> 5 <script type="text/javascript"> 6 document.getElementById("ss").innerHTML = "sdfsdf"; 7 </script> 8 </head> 9 <body> 10 <div id="ss"> 11 dfgdfg 12 </div> 13 </body> 14 </html>
网页上依然会显示"dfgdfg",而不是执行js语句后的形态。使用“谷歌浏览器”审查元素就会发现,提示Uncaught TypeError: Cannot set property 'innerHTML' of null。可是如果将script块放在div的后面就会正常,因为在浏览器从上往下开始解析的时候,解析到第6行的时候,浏览器根本不知道ss这个元素的存在,因此会进行报错,可是如果把js放在后面,在浏览器解析到document.getElementById("ss")时,已经知道了ss是什么东西了,因此浏览器会显示"sdfsdf"。
现在我们再来谈一下传统的web请求,在传统的web应用中,允许用户填写表单,当提交表单时就向web服务器发送一个请求,服务器接收并处理传来的表单,然后返回一个新的网页。可是这样的作法很是浪费带宽,因为在前后的这个页面中大部分HTML往往是相同的。由于每次应用的交互都需要向服务器发送请求,应用的响应时间久依赖于服务器的响应时间。这导致了用户界面的响应比本地应用慢得多。
可是异步传输就不一样,异步传输可以像服务器发送并取回自己必需的数据,不要的数据不必也不需要请求,它使用SOAP或其他一些基于XML的web service接口,并在客户端采用JavaScript处理来自服务器的响应。因此在服务器和路蓝旗的交换的数据大量减少,我们就能看到响应更快的应用。同时很多的处理工作可以在发出请求的客户端上完成,所以服务器的处理时间就会减少。
通过上面的图片,我们就很清楚地看到了异步请求的过程。其实上面的“用户继续执行其他的操作”换成“浏览器继续执行其他的操作”应该更合适一些吧。我们身边有很多这样的异步请求的例子,比如注册用户信息时,用户名不能重复,邮箱不能重复注册,当我们把焦点移开当前输入框时便提示我们用户名和邮箱是否可用,而不是我们以前的那样当提交所有的信息时才提示我们用户名是否可用,这就用到了异步请求ajax技术。
像上面的图片那样,当我们的焦点移开用户名输入框时,浏览器便通过js向服务器请求输入的用户名是否可用,服务器检索数据库检测用户名是否已经存在,然后返回信息,js再根据返回的信息通过浏览器提示用户用户名是否可用;而用户的操作便是将焦点移动到下一个输入框。所有的操作在我们的页面没有任何的跳转和刷新的情况下就完成了。
使用异步请求ajax最大的优点,就是能在不更新整个页面的前提下维护数据。这使得web应用程序更为迅捷地回应用户动作,并避免了在网络上发送那些没有改变过的信息。同时ajax不需要任何浏览器插件,但需要用户的浏览器能够运行js,因为有的用户可能会有意或无意的关闭浏览器js运行,使得某些操作不能进行。
使用ajax非常的方便,而且现在还有很多的js框架封装了ajax的使用,就更加的方便了。下面我就使用传统的javascript方式和jQuery框架两种形式来讲解一下ajax的使用。
传统的javascript方式:(1)创建HttpRequest;(2)向服务器发送请求;(3)服务器响应;(4)处理服务器返回数据。
(1)创建HttpRequest,由于IE的创建方式与其他的浏览器不一样,因此在创建的时候我们应该使用两种方式来创建。
1 function createXMLHttpRequest(){//创建XMLHttpRequest对象 2 if(window.XMLHttpRequest){//非IE浏览器 3 httpRequest = new XMLHttpRequest(); 4 } 5 else if(window.ActiveXObject){ 6 httpRequest = new ActiveXObject("Microsoft.XMLHTTP"); 7 } 8 }
我已经把httpRequest变量声明在了所有函数的外面。
(2)向服务器发送请求,可以调用HTTP请求类的open()和send()方法,具体的调用方式是这样的。
1 url = "card_que_test.php?page="+page+"&pno="+pno+"&pname="+pname+"&identitycard="+identitycard+"&sex="+sex+"&ismarried="+ismarried; 2 3 httpRequest.open("GET", url, true); 4 httpRequest.onreadystatechange = handle;//指定响应函数 5 httpRequest.send(null);
open()的第一个参数HTTP请求方式:GET,POST或任何服务器所支持的方式。按照HTTP规范,该参数要大写;否则某些浏览器(如火狐)可能无法处理请求;第二个参数是请求页面的URL,即当前页面的请求应该由哪个页面来进行处理,如果需要传递参数时,在url后跟上相应的参数;第三个参数为请求是否为异步模式,如果是true,js函数将继续执行,而不等待服务器响应。
(3)服务器响应,上面的代码第4行有一个onreadystatechange,该方法是用来指定由哪个函数来处理服务器返回的数据(注意,被指定的函数后面不带括号,只有函数名);当然,我们也可以直接将处理代码写在onreadystatechange后面,handle()具体的实现方式如下:
1 function handle(){ 2 if(httpRequest.readyState==4){ 3 if(httpRequest.status==200){ 4 var xml = httpRequest.responseText; 5 alert(xml); 6 } 7 } 8 }
看上面的代码,首先要检查请求的状态。只有当一个完整的服务器响应已经收到了,函数才可以处理该响应。httpRequest提供了readyState属性来对服务器响应进行判断。
readyState的取值如下:0(未初始化),1(正在装载),2(装载完毕),3(交互中),4(完成)。只有当readyState==4时,一个完整的服务器响应已经收到了,函数才可以处理该响应。
(4)处理服务器返回数据,从服务器返回的数据可以简单的是一个数字、字符或字符串,也可以是某些复杂的数据类型,如xml,json等。对于这些我们应当分开来进行处理。
下面我们来看一个完整的例子。
第一个文件,我们叫index.html。
1 <html> 2 <head> 3 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 4 <title>upfile</title> 5 </head> 6 <body> 7 <a href="javascript:void(0);" onclick="sendRequest('aa')">aa</a> 8 <a href="javascript:void(0);" onclick="sendRequest('中国')">中国</a> 9 <a href="javascript:void(0);" onclick="sendRequest('123')">123</a> 10 <div id="ss"></div> 11 12 <script type="text/javascript"> 13 var httpRequest; 14 //创建httpRequest对象 15 function createHttpRequest(){ 16 if(window.XMLHttpRequest){ 17 httpRequest = new XMLHttpRequest(); 18 }else{ 19 httpRequest = new ActiveObject("Microsoft.XMLHTTP"); 20 } 21 } 22 23 //向服务器发送请求 24 function sendRequest(s){ 25 createHttpRequest(); 26 27 httpRequest.open("GET", "test.php?s="+s, true); 28 httpRequest.onreadystatechange = handle; 29 httpRequest.send(null); 30 } 31 32 33 //处理数据 34 function handle(){ 35 if(httpRequest.readyState==4){ 36 var text = httpRequest.responseText; 37 document.getElementById("ss").innerHTML = text; 38 } 39 } 40 </script> 41 </body> 42 </html>
第二个文件,我们叫test.php
1 <?php 2 if(isset($_GET['s'])){ 3 $s = $_GET['s']; 4 $str = ""; 5 for($i=0; $i<5; $i++){ 6 $str .= $s; 7 } 8 echo "<font color='red'><b>{$str}</b></font>"; 9 exit(); 10 } 11 ?>
上面的例子很简单,我们将index.html中的请求发送到test.php中进行处理,然后返回结果。运行上面的两个文件,我们就会发现,点击aa就会出现一堆红色加粗的aa,点击中国就会出现一堆红色加粗的中国,点击123就会出现一堆红色加粗的123,而页面并没有跳转或者刷新。这是异步传输ajax。
下面我们来讲解使用jQuery框架来执行异步传输。
其实jQuery的原理与使用传统的js是一样的,只不过jQuery框架封装了ajax,使用起来更加的方便。不过在此之前我们应该jQuery包,否则不能正常使用。
$.ajax({
url: 'test.php',
type: 'POST',
data: 's='+s,
dataType: 'json',
success: function(msg){
//服务器成功返回数据后进行的操作
...
}
});
我们常用的参数也就这几个,不过其他的参数还有很多。当然,我们还应该注意的是,每个参数结束后,应该使用逗号而不是分号结束,否则会报错的。
参数列表:
参数名 | 类型 | 描述 |
url | String | (默认: 当前页地址) 发送请求的地址。 |
type | String | (默认: "GET") 请求方式 ("POST" 或 "GET"), 默认为 "GET"。注意:其它 HTTP 请求方法,如 PUT 和 DELETE 也可以使用,但仅部分浏览器支持。 |
timeout | Number | 设置请求超时时间(毫秒)。此设置将覆盖全局设置。 |
async | Boolean | (默认: true) 默认设置下,所有请求均为异步请求。如果需要发送同步请求,请将此选项设置为 false。注意,同步请求将锁住浏览器,用户其它操作必须等待请求完成才可以执行。 |
beforeSend | Function | 发送请求前可修改 XMLHttpRequest 对象的函数,如添加自定义 HTTP 头。XMLHttpRequest 对象是唯一的参数。function (XMLHttpRequest) { |
cache | Boolean | (默认: true) jQuery 1.2 新功能,设置为 false 将不会从浏览器缓存中加载请求信息。 |
complete | Function | 请求完成后回调函数 (请求成功或失败时均调用)。参数: XMLHttpRequest 对象,成功信息字符串。function (XMLHttpRequest, textStatus) { |
contentType | String | (默认: "application/x-www-form-urlencoded") 发送信息至服务器时内容编码类型。默认值适合大多数应用场合。 |
data | Object, String |
发送到服务器的数据。将自动转换为请求字符串格式。GET 请求中将附加在 URL 后。查看 processData 选项说明以禁止此自动转换。必须为 Key/Value 格式。如果为数组,jQuery 将自动为不同值对应同一个名称。如 {foo:["bar1", "bar2"]} 转换为 '&foo=bar1&foo=bar2'。 |
dataType | String |
预期服务器返回的数据类型。如果不指定,jQuery 将自动根据 HTTP 包 MIME 信息返回 responseXML 或 responseText,并作为回调函数参数传递,可用值: "xml": 返回 XML 文档,可用 jQuery 处理。 "html": 返回纯文本 HTML 信息;包含 script 元素。 "script": 返回纯文本 JavaScript 代码。不会自动缓存结果。 "json": 返回 JSON 数据 。 "jsonp": JSONP 格式。使用 JSONP 形式调用函数时,如 "myurl?callback=?" jQuery 将自动替换 ? 为正确的函数名,以执行回调函数。 |
error | Function | (默认: 自动判断 (xml 或 html)) 请求失败时将调用此方法。这个方法有三个参数:XMLHttpRequest 对象,错误信息,(可能)捕获的错误对象。function (XMLHttpRequest, textStatus, errorThrown) { |
global | Boolean | (默认: true) 是否触发全局 AJAX 事件。设置为 false 将不会触发全局 AJAX 事件,如 ajaxStart 或 ajaxStop 。可用于控制不同的Ajax事件 |
ifModified | Boolean | (默认: false) 仅在服务器数据改变时获取新数据。使用 HTTP 包 Last-Modified 头信息判断。 |
processData | Boolean | (默认: true) 默认情况下,发送的数据将被转换为对象(技术上讲并非字符串) 以配合默认内容类型 "application/x-www-form-urlencoded"。如果要发送 DOM 树信息或其它不希望转换的信息,请设置为 false。 |
success | Function | 请求成功后回调函数。这个方法有两个参数:服务器返回数据,返回状态function (data, textStatus) {
|
1 <html> 2 <head> 3 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 4 <title>upfile</title> 5 </head> 6 <body> 7 <a href="javascript:void(0);" onclick="sendRequest('aa')">aa</a> 8 <a href="javascript:void(0);" onclick="sendRequest('中国')">中国</a> 9 <a href="javascript:void(0);" onclick="sendRequest('123')">123</a> 10 <div id="ss"></div> 11 <!--调用谷歌托管的jQuery--> 12 <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script> 13 <script type="text/javascript"> 14 function sendRequest(s){ 15 $.ajax({ 16 url: 'test.php', 17 type: 'get', 18 data: 's='+s, 19 dataType: 'json', 20 success: function(msg){ 21 $("#ss").html(msg.info); 22 } 23 }) 24 } 25 </script> 26 </body> 27 </html>
index.html修改成这样依然能够实现一样的功能,可是代码量却更好,所以我更推荐使用jQuery来编写js,jQuery有很多的优点,这里就不多说了。好了,异步传输ajax就到这里吧。