4.1 认识AJAX

目前绝大多数网站都直接或间接使用了AJAX技术,它是一种支持良好的、公开标准的、久经检验的、可放心使用的技术。

4.1.1 AJAX是技术不是编程语言

AJAX不是一门和C语言类似的编程语言,是聪明的程序员对JavaScript的第一次创造性用法。第二次对JavaScript的创造性用法则是后面要讲到的Node.js技术。

AJAX这个词最早是AJAX之父Jesse James Garrett于2005年2月在Ajax: A New Approach to Web Applications中提出来的,是Asynchronous JavaScript And XML(异步JavaScript和XML)的简称。它基于已有的标准,而这些标准已被使用多年,所有现代浏览器都支持AJAX的实现,包括老掉牙的IE 6,甚至几乎快灭绝的IE 5。

虽然文章的传播提高了人们使用该项技术的意识,但最早使用这种技术的历史可以追溯到1998年,由微软的项目小组率先使用。直到后来Google通过其Google Suggest等产品使AJAX变得流行起来。

Google Suggest使用AJAX创造出了动态性极强的Web界面:当在谷歌的搜索框输入关键字时,JavaScript会把这些字符发送到服务器,然后服务器会返回一个搜索建议的列表,其中之一就是我们最常见到的自动完成。百度类似Google Suggest的应用如图4-1所示。

图4-1 在百度搜索中的自动完成

AJAX前景非常乐观,可以提高系统性能,优化用户界面,学习简单,开发方便。就目前而言,很多著名JavaScript框架都有AJAX相关的API,包括本书讲到的jQuery。

4.1.2 同步与异步

AJAX中的Asynchronous就是异步的意思,这是相对于传统同步方式而言的。

异步传输基于字符,同步传输基于比特。同步传输的时候要求接收端和发送端保持通信一致,而异步则不要求。理解这个差异最常见的例子是键盘和主机的通信,按一个键就发送按键值,主机不知道用户何时会按键,所以主机必须随时能接收。

在Web网页上也体现出一组同步和异步的情况,下面通过【范例4-1】来说明。

【范例4-1 js文件加载时的异步】

    1.      <html>
    2.       <head>
    3.         <title>async or sync</title>
    4.       </head>
    5.       <body>
    6.       <div id="msg"></div>
    7.      <script>
    8.               var async= document.createElement('script');
    9.              //文件内容仅是:document.getElementById("msg").innerHTML+="async<br/>";
    10.             async.src='4-1.async.js? r='+Math.random()*99;
    11.             document.body.appendChild(sync);
    12.     </script>
    13.    <! --文件内容仅是document.getElementById("msg").innerHTML+="sync<br/>"; -->
    14.     <script src="4-1.sync.js"></script>
    15.      </body>
    16.     </html>

在标准浏览器下运行代码后会发现,可能先会输出“sync”的字符串,然后才是“async”。网页是自上而下执行代码的,为什么明明操作“async”的代码在前面却不能保证一定先执行呢?这里存在网络通信不一致的情况和浏览器缓存问题。

从直观上来看,这就是个先后问题,从技术深层去看,它不是什么线程问题,而是设计思想问题。

异步模式是一个巨大的进步,当打开一个网页时,花费很多时间等待服务器提供给用户的信息可能很多是用户不想要的,在同步时代,这就是很大的浪费。当然异步模式的产生也有其更为复杂的因素。

通过AJAX技术,JavaScript异步操作时无须等待服务器的响应,而是:


● 在等待服务器响应时执行其他脚本或任务。

● 当响应就绪后对响应数据进行处理。

4.1.3 AJAX与JSON

AJAX提供与服务器异步通信的能力,一个最简单的应用是无须刷新整个页面而在网页中更新一部分数据。因此,AJAX可使Web应用程序更小、更快、更友好。

AJAX包括异步、JavaScript和XML,这是最初的外延,目前,JSON已经成为流行的数据交换格式之一,在实际Web应用中,JSON已逐步代替了XML格式,成为AJAX实践中最主要的数据交换格式。

可以通过【范例4-2】和【范例4-3】简单了解一下XML和JSON数据格式。

【范例4-2 最简单的XML格式】

    1.      <? xml version="1.0" encoding="UTF-8"? >
    2.      <user>
    3.               <name>z3f</name>
    4.               <homepage>www.z3f.me</homepage>
    5.      </user>
    1.      {"name":"z3f", "homepage":"www.z3f.me"}

【范例4-3 最简单的JSON格式】

通过范例可以看出,JSON相对于XML而言更小、解析更快,如果在Internet中传输会更加节省流量,正由于此,JSON才成为一种重要的、广泛应用于Internet的、JavaScript语言中的数据交换格式。本书范例也将大量使用JSON,更为详细的介绍将在后续章节谈到。

JSON的发明人是前雅虎架构师道格拉斯·克洛克福特(Douglas Crockford)。他的JSON让AJAX活力倍增,几乎完胜XML,由于习惯问题,AJAX中的X依然是指XML,而实际上大多数项目却使用的是JSON。

JSON在网络中传输时是字符串形式,在JavaScript中解析后就是Object对象,即序列化和反序列化。

4.1.4 AJAX是如何工作的

通过【范例4-4】这个小型AJAX应用程序范例来快速理解AJAX的工作原理。布局好HTML代码,设置一个按钮,通过按钮的click事件触发AJAX相关操作代码。在AJAX代码中首先创建一个XMLHttpRequest对象,通过对象的open方法和send方法发送GET请求,把服务器发回的结果替换为指定内容。在这里把前面的JavaScript代码整理成独立的eg.lib.js公共方法文件,以便管理。

【范例4-4 helloajax】

    1.  <html>
    2.    <head>
    3.     <title>hello ajax</title>
    4.    </head>
    5.    <body>
    6.      <div id="myajax">hello world! </div>
    7.      <button type="button" id="ajaxBtn">通过 AJAX 改变内容</button>
    8.      <script src="eg.lib.js"></script>
    9.    </body>
    10. </html>
    11. <script>
    12.    //定义一个公用的AJAX 请求函数
    13.    eg.AJAX = function(config, callback){     //接受一个回调函数和一个配置参数
    14.             var xmlhttp;                          //定义一个变量用于后面存储对象
    15.             if(window.XMLHttpRequest){         //如果浏览器支持XMLHttpRequest 对
                                                        象,通常非IE 浏览器支持
    16.                      xmlhttp = new XMLHttpRequest();
    17.             }else if(window.ActiveXObject){
                    //如果浏览器支持ActiveXObject 对象,通常是IE
    18.                     try {  //尝试创建一个低版本对象,msxml 组件2.6 版本以下支持
    19.                              xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    20.                      }
    21.                      catch (e){
    22.                             try {  //尝试创建一个高版本对象,msxml 组件3.0 版本以上支持
    23.                                       xmlhttp=new ActiveXObject("msxml2.XMLHTTP");
    24.                              }
    25.                              catch (x){
    26.                              }
    27.                      }
    28.             }
    29.             if(xmlhttp){  //如果能够创建成功(一般都会成功)
    30.                      if(config.ISASYN){
    31.                              xmlhttp.onreadystatechange = function(){
                                  //定义HTTP 状态发生改变时执行的函数
    32.                                       if (xmlhttp.readyState==4 && xmlhttp.status
                                          ==200){   //当HTTP 请求成功时
    33.                              callback(xmlhttp.responseText, xmlhttp.responseXML);
                                //把服务器响应的数据回传给回调函数callback
    34.                                       }
    35.                              };
    36.                             //将传递的参数给open 方法调用
                                xmlhttp.open(config.TYPE, config.URL, true);
    37.                             xmlhttp.send(config.DATA); //发送异步AJAX 请求
    38.                      }else{
    39.                             //将传递的参数给open 方法调用
                                xmlhttp.open(config.TYPE, config.URL, false);
    40.                             xmlhttp.send(config.DATA); //发送同步AJAX 请求
    41.                              callback(xmlhttp.responseText, xmlhttp.responseXML);
    42.                      }
    43.             }
    44.     };
    45. (function(){     //避免全局污染,将操作放在闭包里
    46.       var ajaxBtn = eg.$("ajaxBtn");
              //取得username 的DOM 对象,eg.$方法定义在eg.lib.js,详见第2 章中的范例
    47.       //给userName 对象绑定一个onkeyup 事件,eg.addListener 方法定义在eg.lib.
              js,详见第2 章中的范例
    48.       eg.addListener(ajaxBtn, "click", function(){
    49.             eg.AJAX({TYPE:"GET", //AJAX 请求类型
    50.             URL:"4-4.txt",  //AJAX 请求的URL,该文件只有hello ajax 字符串的纯文本
    51.             ISASYN:true           //是否异步
    52.             }, function(data){    //定义AJAX 请求成功后的callback 回调函数
    53.                          //在元素myajax 原本的hello world!会变成hello ajax
                            eg.$("myajax").innerHTML = data;
    54.             });
    55.     });
    56. })();
    57. </script>

将【范例4-4】的代码直接另存为html文件无法直接运行,需要放在网站下,还需要在同目录下新建一个保存“hello ajax”字符串的txt文件,可自定义内容和进行名字测试,在火狐浏览器中的运行效果如图4-2所示。

图4-2 在火狐上运行的效果

IE等浏览器也能够执行【范例4-4】中的代码,对于公共函数eg.AJAX,为了便于管理,最好将其移至eg.lib.js中,后期直接引用eg.lib.js文件即可,而且HTML代码非常简洁。