传统的 web 应用允许用户端填写表单(form),当提交表单时就向网页服务器发送一个请求。服务器接收并处理传来的表单,然后送回一个新的网页,但这个做法浪费了许多带宽,因为在前后两个页面中的大部分 html 码往往是相同的。由于每次应用的沟通都需要向服务器发送请求,应用的回应时间依赖于服务器的回应时间。这导致了用户界面的回应比本机应用慢得多。
2005 年 2 月 18 号,一位大佬,名叫 Jesse James Garrett(杰西 · 詹姆斯 · 贾瑞特),发表了一篇文章叫做 "Ajax: A new Approach to Web Applications",介绍了一种技术叫做 Asynchronous JavaScript and XML,这项技术能够向服务器请求额外的数据而不需要重新加载页面,这样就可以部分请求数据而不需要刷新整个页面,不仅仅节约了大量的带宽,还加快了响应速度。
-- 摘自维基百科并稍作修改
XHR 全称是 XMLHttpRequest,可扩展超文本传输请求,是一个 API,它通过 URL 在客户端和服务器端传输数据而不需要使页面刷新,提供了对 HTTP 协议的完全的访问,是 AJAX 技术的核心对象,AJAX 的请求过程可以据此分为四个部分:
- 创建 XMLHttpRequest 对象
- 连接后台服务器
- 发送数据请求
- 接收服务器的响应数据;
XHR 对象在 IE5 中第一次引入,对象是通过 MSXML 库中的一个 ActiveX 对象实现的。因而 IE 中可能遇到三种不同版本的 XHR 对象:MSXML2.XMLHttp、MSXML2.XMLHttp.3.0、MSXML2.XMLHttp.6.0。IE7+、Firefox、Opera、Chrome 和 Safari 都支持原生的 XHR 对象。
如果要兼容 IE7 之前的浏览器的话,要根据不同的 XHR 版本来编写函数,再创建 ActiveXObject 对象,而其他的浏览器,则可以直接创建 XMLHttpRequest 对象。代码如下:
- function createXHR() {
- if (typeof XMLHttpRequest != "undefined") {
- return new XMLHttpRequest();
- } else if (typeof ActiveXObject != "undefined") {
- if (typeof arguments.callee.activeXString != "string") {
- var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp"],
- i,
- len;
- for (i = 0, len = versions.length; i < len; i++) {
- try {
- new ActiveXObject(versions[i]);
- arguments.callee.activeXString = versions[i];
- break;
- } catch(ex) {
- //跳过
- }
- }
- }
- return new ActiveXObject(arguments.callee.activeXString);
- } else {
- throw new Error("No XHR object available.");
- }
- }
- var xhr = createXHR();
不过现在一般很少人想要兼容 IE7 之前的版本了,于是可以简化如下:
- var xhr = new XMLHttpRequest();
XMLHttpRequest 连接服务器也不难:
- xhr.open(method, url, async, user, password)
使用以上的 open 方法来初始化一个请求即可,open 方法的参数说明如下:
- method:
- 请求所使用的HTTP方法; 例如 "GET", "POST", "PUT", "DELETE"等. 如果下个参数是非HTTP(S)的URL,则忽略该参数.
- url:
- 该请求所要访问的URL
- async:
- 一个可选的布尔值参数,默认为true,意味着是否执行异步操作,如果值为false,则send()方法不会返回任何东西,直到接受到了服务器的返回数据。如果为值为true,一个对开发者透明的通知会发送到相关的事件监听者。这个值必须是true,如果multipart 属性是true,否则将会出现一个意外。
- user:
- 用户名,可选参数,为授权使用;默认参数为空string.
- password:
- 密码,可选参数,为授权使用;默认参数为空string.
method 方法中最常用的请求类型便是 GET 和 POST,一般情况下:
- 1、GET用于向服务器查询某些信息,而POST向服务器发送要保存的数据。
- 2、GET将查询字符串参数追加到URL的末尾发给服务器,而POST通过传递参数给send()方法发送数据。
举个栗子:
- if (method == "GET") {
- xhr.open("GET", url + "?" + params, true);
- xhr.send(null);
- } else if (method == "POST") {
- xhr.open("POST", url, true);
- //设置表单提交时的内容类型
- xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
- xhr.send(params);
- }
如上所示,GET 请求是直接在 URL 后面添加 ?+parm_name=parm_value&…… 来传递数据,然后 xhr.send(null)(注:null 不能省略)
- http://www.yourhost.com?username="myname"&password="123"
而 POST 请求则是模拟表单提交,将头部信息设置为表单提交时的内容类型,然后将 params 当做 send() 方法的参数传递给服务器。
在调用 send() 方法后,请求便会派发到服务器,服务器对请求进行处理后作出响应。然后自动填充到 XHR 对象的属性中。
- responseText:作为响应主体被返回的文本。
- responseXML:如果响应的内容类型是"text/xml"或"application/xml",这个属性中将保存包含着响应数据的XML DOM 文档。
- status:响应的HTTP 状态。
- statusText:HTTP 状态的说明。
我们根据检测 XHR 对象中的 readyState 属性,可以获取当前的响应状态:
- :未初始化。尚未调用open()方法。
- :启动。已经调用open()方法,但尚未调用send()方法。
- :发送。已经调用send()方法,但尚未接收到响应。
- :接收。已经接收到部分响应数据。
- :完成。已经接收到全部响应数据,而且已经可以在客户端使用了。
一般而言,我们只对状态 "4" 感兴趣,而 readyState 每次更改,都会触发一次 readystatechange 监听事件,因此,我们可以通过在监听函数中判断 readyState 的来判断响应是否成功,并取得响应数据。
- xhr.onreadystatechange = function() {
- if (xhr.readyState == 4) {
- //200-300表示成功返回,304表示资源未修改
- if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
- //在这里对响应数据进行处理(保存、打印等)
- console.log(xhr.responseText);
- } else {
- alert("Request was unsuccessful: " + xhr.status);
- }
- }
- };
至此,一次完整的 AJAX 请求就已经完成了:
- //创建
- var xhr = createXHR();
- //监听状态、处理数据
- xhr.onreadystatechange = function() {
- if (xhr.readyState == 4) {
- if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
- //对xhr.responseText响应数据进行处理;
- } else {
- alert("Request was unsuccessful: " + xhr.status);
- }
- }
- };
- //连接
- xhr.open("get", "/xxx/xxx?param1=value1¶m2=value2", true);
- //发送
- xhr.send(null);
- function createXHR() {
- if (typeof XMLHttpRequest != "undefined") {
- return new XMLHttpRequest();
- } else if (typeof ActiveXObject != "undefined") {
- if (typeof arguments.callee.activeXString != "string") {
- var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp"],
- i,
- len;
- for (i = 0, len = versions.length; i < len; i++) {
- try {
- new ActiveXObject(versions[i]);
- arguments.callee.activeXString = versions[i];
- break;
- } catch(ex) {}
- }
- }
- return new ActiveXObject(arguments.callee.activeXString);
- } else {
- throw new Error("No XHR object available.");
- }
- }
参考资料:
1、XMLHttpRequest-MDN
2、《JavaScript 高级程序设计(第三版)》
来源: http://www.cnblogs.com/ljwTiey/p/7405834.html