首页 > 代码库 > JavaScript大杂烩12 - 理解Ajax

JavaScript大杂烩12 - 理解Ajax

AJAX缘由

  再次谈起这个话题,我深深的记得就在前几年,AJAX被炒的如火如荼,就好像不懂AJAX,就不会Web开发一样。要理解AJAX为什么会出现,就要先了解Web开发面临的问题。

  我们先来回忆一下Web页面的申请过程,这个咱们在第一篇中就介绍过了:Web页面开发就是在无连接和无状态的HTTP协议上管理页面的状态。每次申请页面的时候,服务器都会返回完整的HTML文本(当然还有其他的文本文件),浏览器就负责解析这个文本并在浏览器中显示。

  在这个过程中,不管当前页面的内容是不是都变化了,服务器都会重新给浏览器重发一份,这个操作对于原本就比较脆弱的网络来说,实在是比较耗时,比较低效,虽然时至今日,这种方式还是很多网站的工作模式,但是还有有很多玩家开始思考如何去优化这个过程。在编程语言的发展过程中,异步是解决用户响应问题的不二法宝,所以异步的申请与局部更新的方案就产生了,这个就是AJAX。

 

问题的本质 - 数据交互技术

  在详细总结Ajax的实践之前,我们先来深入的分析一下问题的核心。

  任何的软件程序基本上都可以分为界面(UI),逻辑,数据3个部分,Web程序也不例外,在Web程序中,JavaScript承担了完成逻辑功能的任务,也就是和后台数据打交道的任务,不管是用户输入,还是获取数据,最终都表现为使用JavaScript完成与服务器的交互,这样的操作说白了就是前端界面与后端数据之间的数据交互问题。

  数据交互的方式基本上也就是两种方式:同步和异步,前者会等待数据操作结束后继续执行下面的程序,后者不会等待数据操作完成,而是先执行下面的程序,在数据操作完成后再通过回调函数完成需要执行的一些工作。

  而在执行数据交互的过程中,前后端也可以采取不同的联系方式:持续连接和按需连接,前者前后端一直保持连接,后者前后端只在需要的时候连接一下。

  对于传统的桌面程序,由于前端与后端共存与一台机器上,所以访问比较方便,通常采用持续连接和同步访问的方式,而对于一些大数据量的操作才采用异步访问的方式(提高界面的可响应性)。

  对于Web程序而言,由于前后端通常不在一台机器上,而且最初网络环境并不是太好,所以最初采用的是按需连接(申请页面的时候建立连接)和同步的方式(数据接收完毕后更新整个页面)。但是随着Web程序需求(功能性和非功能性需求)的不断提高,网络软硬件技术的不断发展,数据访问方式就理所当然的出现了异步的方式和局部更新,这就是AJAX技术。而随着HTML5技术的逐渐发展,持续连接也成为了一种可能,这就是WebSocket技术,这个在前面的HTML5系列文章中已经总结过了。

  从上面的数据交互技术发展的核心脉络中我们可以更清楚的理解AJAX所处的历史地位和积极意义,下面我们就详细的看一下AJAX技术。

 

AJAX本质

AJAX = Asynchronous JavaScript and XML (异步的 JavaScript 和 XML)

  AJAX就是在客户端申请页面时,在不重新加载整个页面的情况下,只对网页的局部进行更新的技术。使用了AJAX后,浏览器与服务器只会进行少量数据交换,这样页面的执行效率就会大幅提升。

  AJAX实现的核心有两点:

1. 异步申请数据

2. 响应数据,更新局部页面

  更新页面比较简单,前面DOM部分已经总结过常见的CRUD(创建,检索,更新,删除)操作了。那个剩下的的就是如何异步的申请和响应服务端的数据了,这个是通过AJAX的核心对象XMLHttpRequest来完成的。

  总的来说,XMLHttpRequest对象很简单,下面来看个简单的例子:

<html><head><script type="text/javascript">var xmlhttp;function loadXMLDoc(url){  xmlhttp = null;  // 1. 创建XMLHttpRequest对象  if (window.XMLHttpRequest){    // 适用于浏览器IE7, Firefox, Opera, Chrome等    xmlhttp = new XMLHttpRequest();  }  else if (window.ActiveXObject) {    // 适用于浏览器 IE6, IE5    xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");  }   if (xmlhttp != null) {    // 2. 挂接响应函数/回调函数    xmlhttp.onreadystatechange = stateChange;    // 3. 设置申请方法    xmlhttp.open("GET",url,true);    // 4. 发送申请    xmlhttp.send();  } else {    alert("你的浏览器不支持XMLHTTP");  }}function stateChange() {  // readyState = 4(loaded)并且status = 200(OK)代表申请数据成功  if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {    // 获取响应的状态,返回的数据(XML格式)    document.getElementById(A1).innerHTML = xmlhttp.status;    document.getElementById(A2).innerHTML = xmlhttp.statusText;    document.getElementById(A3).innerHTML = xmlhttp.responseText;  } else {    alert("获取XML时出错:" + xmlhttp.statusText);  }}</script></head><body>  <h2>使用HttpRequest对象</h2>  <p><b>状态:</b>  <span id="A1"></span>  </p>  <p><b>状态文本:</b>  <span id="A2"></span>  </p>  <p><b>返回的数据:</b>  <br /><span id="A3"></span>  </p>  <button onclick="loadXMLDoc(‘/example/xmle/note.xml‘)">获取XML</button></body></html>

  直接运行这个例子是不行的,需要自己配置个服务器,这个例子来源于W3C,地址:http://www.w3school.com.cn/tiy/t.asp?f=ajax_httprequest_js。我只不过是加了一下注释,下面就是例子的一些说明。

1. 创建XMLHttpRequest对象

  兼容性问题注意一下即可。

2. 向服务器发送请求

  申请时我们使用了XMLHttpRequest对象的open()和send()方法。

  open方法的第一个参数指定了请求的方式是GET或者是POST。与POST相比,GET更简单也更快,并且在大部分情况下都能用。

  然而,在以下情况中,则需要使用POST请求:

1).无法使用缓存文件(更新服务器上的文件或数据库)

2).向服务器发送大量数据(POST没有数据尺寸限制)

3).发送包含未知字符的用户输入时,POST比GET更稳定也更可靠(其实还是考虑数据尺寸的限制问题)

  其实说白了POST主要用于携带数据更新服务器然后返回。

  open方法的第二个参数是申请的数据url,这个没什么好说的。

  open方法的第三个参数是指定申请时异步(true)还是同步(false),这个其实不用考虑,估计没什么人使用同步方式。如果有些兄弟想试验一下同步的方式的话,也可以,不过响应的函数就不用挂到onreadystatechange上了,而是直接在send方法后面写上更新HTML的代码即可。

  send方法发送请求,这个方法可以携带一个字符串作为参数,这个参数存储了发送给服务器的数据,简单的申请都不用给服务器发送数据,所以用法都很简单:

xmlhttp.open("POST","demo_post.asp",true);xmlhttp.send();

  如果要像HTML表单那样POST数据的话,一般还要设置HTTP头,所以复杂一点的POST申请的代码大概像是这样:

xmlhttp.open("POST","ajax_test.asp",true);xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");xmlhttp.send("fname=Bill&lname=Gates");

  这其实是更新服务器数据的操作。

3. 响应服务器端的数据

  这个响应函数对于同步的申请来说很简单,直接把代码写到send方法的后面就可以了。异步申请的话要挂接到onreadystatechange事件上。

  在回调函数中,我们首先需要判断服务器的处理状态,这就是通过判断例子中的readyState和status来实现的。只有readyState等于4并且status等于200的时候才表明服务器正确的返回了申请的数据,这个时候我们通过responseText或者responseXML获取到字符串格式或者XML格式的数据,然后解析处理就行了。

 

再论JSON与XML

  在AJAX中,名字中的异步XML确实是相当惊艳,在回调函数中,直接可以使用responseXML访问XML格式的内容。不过鉴于在JavaScript中解析XML实在有点不是太方便(感兴趣的同学百度一把就知道了),至少是比解析JSON要麻烦一点,所以就像在前面我们讨论的那样:WEB开发中,JSON是王道。虽然XML是AJAX内置的一种方式,而且现实世界中确实也存在很多构建在XML或者SOAP(一种轻量的、简单的、基于XML的协议)之上的服务方式,但是除了这些必须要使用XML的服务外,使用JSON确实能带来不少的方便。

 

REST思想

  每次看到介绍AJAX的文章,我总能在第一时间想到REST架构。

  REST是英文Representational State Transfer的缩写,中文翻译为“表述性状态转移”。这个又是当前炙手可热的一个概念。这种思想的核心就是使用单一的URI标示符去标识服务器上的任何的资源,客户端使用URI去对资源进行CRUD操作。这种想法与AJAX的做法配合起来(基于REST的Web服务及基于 Ajax的客户端)可以说是十分融洽。关于REST思想,后面会专门总结它,感兴趣的同学可以先看看这个链接中的例子:http://www.ibm.com/developerworks/cn/webservices/ws-restajax/。

 

单页面的思想

  单页面就是只有一个页面的Web程序,所有的操作都在同一个页面中完成,所有的数据交互都通过AJAX或者WebSocket完成,使用这些程序的感觉就如同使用桌面程序一样。单页面程序开发也是近年来比较火的一种开发方式,很多的公司都针对这种方式开发了相应的类库,比如谷歌的AngularJS,AJAX是构建单页面程序的核心技术之一。

  单页面技术与REST模式并不是万能的,它们与AJAX紧密相关,但是又有很多的实际问题没有解决,所以大多时候,大家还是习惯把它们与别的技术,例如MVC结合起来使用。 

 

参考资料:

一个完美的Web Ajax开发教程:https://www.ibm.com/developerworks/cn/views/xml/libraryview.jsp?sort_by=&show_abstract=true&show_all=&search_flag=&contentarea_by=%E6%89%80%E6%9C%89%E4%B8%93%E5%8C%BA&search_by=%E6%8E%8C%E6%8F%A1+Ajax&topic_by=-1&type_by=%E6%8A%80%E6%9C%AF%E6%96%87%E7%AB%A0&ibm-search=%E6%90%9C%E7%B4%A2

替代Ajax的一些技术:http://www.ibm.com/search/csass/search/?q=%E5%8F%8D%E5%90%91Ajax&dws=cndw&ibm-search.x=12&ibm-search.y=16&ibm-search=Search&sn=dw&lang=zh&cc=CN&ddr=&en=utf&lo=zh&hpp=20