什么是异步传输,首先让我们看看传统的数据加载方式“同步传输”,传统的页面加载一般是从上开始往下加载的,当需要加载 js 的时候,是阻塞加载,当引用了 js 的时候,浏览器发送一个 js request 就会一直等待该 request 的返回。
因此这样写会提示错误的:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>up</title>
<script type="text/javascript">
document.getElementById("ss").innerHTML = "sdfsdf";
</script>
</head>
<body>
<div id="ss">dfgdfg</div>
</body>
</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 的使用。
1. 传统的 javascript 方式: #
- 创建 HttpRequest;
- 向服务器发送请求;
- 服务器响应;
- 处理服务器返回数据。
1.1 创建 HttpRequest #
由于 IE 的创建方式与其他的浏览器不一样,因此在创建的时候我们应该使用两种方式来创建。
function createXMLHttpRequest() {
//创建XMLHttpRequest对象
if (window.XMLHttpRequest) {
//非IE浏览器
httpRequest = new XMLHttpRequest();
} else if (window.ActiveXObject) {
httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
}
}
我已经把 httpRequest 变量声明在了所有函数的外面。
1.2 向服务器发送请求 #
可以调用 HTTP 请求类的 open()和 send()方法,具体的调用方式是这样的。
url = "card_que_test.php?page=" + page + "&pno=" + pno + "&pname=" + pname + "&identitycard=" + identitycard + "&sex=" + sex + "&ismarried=" + ismarried;
httpRequest.open("GET", url, true);
httpRequest.onreadystatechange = handle; //指定响应函数
httpRequest.send(null);
open()的第一个参数 HTTP 请求方式:GET,POST 或任何服务器所支持的方式。按照 HTTP 规范,该参数要大写;否则某些浏览器(如火狐)可能无法处理请求;第二个参数是请求页面的 URL,即当前页面的请求应该由哪个页面来进行处理,如果需要传递参数时,在 url 后跟上相应的参数;第三个参数为请求是否为异步模式,如果是 true,js 函数将继续执行,而不等待服务器响应。
1.3 服务器响应 #
上面的代码第 4 行有一个 onreadystatechange,该方法是用来指定由哪个函数来处理服务器返回的数据(注意,被指定的函数后面不带括号,只有函数名);当然,我们也可以直接将处理代码写在 onreadystatechange 后面,handle()具体的实现方式如下:
function handle() {
if (httpRequest.readyState == 4) {
if (httpRequest.status == 200) {
var xml = httpRequest.responseText;
alert(xml);
}
}
}
看上面的代码,首先要检查请求的状态。只有当一个完整的服务器响应已经收到了,函数才可以处理该响应。httpRequest 提供了 readyState 属性来对服务器响应进行判断。
readyState 的取值如下:0(未初始化),1(正在装载),2(装载完毕),3(交互中),4(完成)。只有当 readyState==4 时,一个完整的服务器响应已经收到了,函数才可以处理该响应。
1.4 处理服务器返回数据 #
从服务器返回的数据可以简单的是一个数字、字符或字符串,也可以是某些复杂的数据类型,如 xml,json 等。对于这些我们应当分开来进行处理。
下面我们来看一个完整的例子。
第一个文件,我们叫 index.html:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>upfile</title>
</head>
<body>
<a href="javascript:void(0);" onclick="sendRequest('aa')">aa</a>
<a href="javascript:void(0);" onclick="sendRequest('中国')">中国</a>
<a href="javascript:void(0);" onclick="sendRequest('123')">123</a>
<div id="ss"></div>
<script type="text/javascript">
var httpRequest;
//创建httpRequest对象
function createHttpRequest() {
if (window.XMLHttpRequest) {
httpRequest = new XMLHttpRequest();
} else {
httpRequest = new ActiveObject("Microsoft.XMLHTTP");
}
}
//向服务器发送请求
function sendRequest(s) {
createHttpRequest();
httpRequest.open("GET", "test.php?s=" + s, true);
httpRequest.onreadystatechange = handle;
httpRequest.send(null);
}
//处理数据
function handle() {
if (httpRequest.readyState == 4) {
var text = httpRequest.responseText;
document.getElementById("ss").innerHTML = text;
}
}
</script>
</body>
</html>
第二个文件,我们叫 test.php:
<?php
if(isset($_GET['s'])){
$s = $_GET['s'];
$str = "";
for($i=0; $i<5; $i++){
$str .= $s;
}
echo "<font color='red'><b>{$str}</b></font>";
exit();
}
?>
上面的例子很简单,我们将 index.html 中的请求发送到 test.php 中进行处理,然后返回结果。运行上面的两个文件,我们就会发现,点击 aa 就会出现一堆红色加粗的 aa,点击中国就会出现一堆红色加粗的中国,点击 123 就会出现一堆红色加粗的 123,而页面并没有跳转或者刷新。这是异步传输 ajax。
2. jQuery 中的 ajax #
下面我们来讲解使用 jQuery 框架来执行异步传输。
其实 jQuery 的原理与使用传统的 js 是一样的,只不过 jQuery 框架封装了 ajax,使用起来更加的方便。不过在此之前我们应该 jQuery 包,否则不能正常使用。
$.ajax({
url: "test.php",
type: "POST",
data: "s=" + s,
dataType: "json",
success: function (msg) {
//服务器成功返回数据后进行的操作
// ...
},
});
我们常用的参数也就这几个,不过其他的参数还有很多。当然,我们还应该注意的是,每个参数结束后,应该使用逗号而不是分号结束,否则会报错的。
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>upfile</title>
</head>
<body>
<a href="javascript:void(0);" onclick="sendRequest('aa')">aa</a>
<a href="javascript:void(0);" onclick="sendRequest('中国')">中国</a>
<a href="javascript:void(0);" onclick="sendRequest('123')">123</a>
<div id="ss"></div>
<!--调用谷歌托管的jQuery-->
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
function sendRequest(s) {
$.ajax({
url: "test.php",
type: "get",
data: "s=" + s,
dataType: "json",
success: function (msg) {
$("#ss").html(msg.info);
},
});
}
</script>
</body>
</html>
index.html 修改成这样依然能够实现一样的功能,可是代码量却更好,所以我更推荐使用 jQuery 来编写 js,jQuery 有很多的优点,这里就不多说了。好了,异步传输 ajax 就到这里吧。