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结合起来使用。
参考资料:
JavaScript大杂烩12 - 理解Ajax的更多相关文章
- JavaScript大杂烩11 - 理解事件驱动
前面我们回顾了前端JavaScript只干的两件事:操作BOM与操作DOM,那么什么时候去干这些事呢?答案是需要干的时候去干.那么什么时候是需要干的时候呢?答案是事件被触发的时候.这就是通常所说的“事 ...
- JavaScript大杂烩1 - 理解JavaScript的类型系统
随着硬件水平的逐渐提高,浏览器的处理能力越来越强大,本人坚信,客户端会越来越瘦,瘦到只用浏览器就够了,服务端会越来越丰满:虽然很多大型的程序,比如3D软件,客户端仍然会存在,但是未来的主流必将是浏览器 ...
- JavaScript大杂烩10 - 理解DOM
操作DOM 终于到了JavaScript最为核心的部分了,通常来说,操作DOM,为页面提供更为友好的行为是JavaScript根本目标. DOM树 - HTML结构的抽象 既然DOM是操纵HTML ...
- JavaScript大杂烩9 - 理解BOM
毫无疑问,我们学习JavaScript是为了完成特定的功能.在最初的JavaScript类型系统中,我们已经分析过JavaScript在页面开发中充当着添加逻辑的角色,而且我们知道JavaScript ...
- JavaScript大杂烩8 - 理解文本解析的"黄金搭档"
文本解析"黄金搭档" - String与RegExp对象 文本解析是任何语言中最常用的功能,JavaScript中也是一样,而正则表达式作为最常用的方式,JavaScript也同样 ...
- JavaScript大杂烩7 - 理解内置集合
JavaScript内置了很多对象,简单的类型如String,Number,Boolean (相应的"值类型"拥有相同的方法),复杂一点的如Function,Object,Arra ...
- JavaScript大杂烩6 - 理解JavaScript中的this
在JavaScript开发中,this是很常用的一个关键字,但同时也是一个很容易引入bug的一个关键字,在这里我们就专门总结一下页面中可能出现的this关键字(包括几种在其他页面文件中出现的this) ...
- JavaScript大杂烩4 - 理解JavaScript对象的继承机制
JavaScript是单根的完全面向对象的语言 JavaScript是单根的面向对象语言,它只有单一的根Object,所有的其他对象都是直接或者间接的从Object对象继承.而在JavaScript的 ...
- JavaScript大杂烩3 - 理解JavaScript对象的封装性
JavaScript是面向对象的 JavaScript是一种基于对象的语言,你遇到的所有东西,包括字符串,数字,数组,函数等等,都是对象. 面向过程还是面向对象? JavaScript同时兼有的面向过 ...
随机推荐
- Liferay7 BPM门户开发之11: Activiti工作流程开发的一些统一规则和实现原理(完整版)
注意:以下规则是我为了规范流程的处理过程,不是Activiti公司的官方规定. 1.流程启动需要设置启动者,在Demo程序中,“启动者变量”名统一设置为initUserId 启动时要做的: ident ...
- python --第三方登录--微博
理解第三方登录的流程: 用户向本地应用商城发起请求,我要用微博进行登录 我们的商城凑一个url让用户跳转到第三方应用的url(微博的登录页面) 用户在该界面点击输入用户名密码之后,点击授权. 微博有个 ...
- 什么是js的严格模式
设立严格模式的原因: - 消除Javascript语法的一些不合理.不严谨之处,减少一些怪异行为; - 消除代码运行的一些不安全之处,保证代码运行的安全: - 提高编译器效率,增加运行速度: - 为未 ...
- 学习之响应式Web设计---一个实例
周末闲来无事,做了一个响应式设计的例子.当然,由此并不能窥见响应式设计真谛之一斑.但,对于初次接触响应设计,对于响应式设计的概念依旧模糊不清的同学来说,或许是个启蒙! 闲语暂且不表,进入正题,这里没有 ...
- Spring Boot应用的后台运行配置(转载)
作者:程序猿DD 酱油一篇,整理一下关于Spring Boot后台运行的一些配置方式.在介绍后台运行配置之前,我们先回顾一下Spring Boot应用的几种运行方式: 运行Spring Boot的应用 ...
- 让Java线程池实现任务阻塞执行的一种可行方案
Java的线程池一般是基于concurrent包下的ThreadPoolExecutor类实现的, 不过当我们基于spring框架开发程序时, 通常会使用其包装类ThreadPoolTaskExecu ...
- C#效率优化(1)-- 使用泛型时避免装箱
本想接着上一篇详解泛型接着写一篇使用泛型时需要注意的一个性能问题,但是后来想着不如将之前的详解XX系列更正为现在的效率优化XX系列,记录在工作时遇到的一些性能优化的经验和技巧,如果有什么不足,还请大家 ...
- mac在命令行中打开某个文件夹
使用 open 命令,如打开 ~/Download/abc open ~/Download/abc
- php实现猴子选大王
function getKing($n,$m) { $arr = range(1,$n); $i = 0; while(count($arr) > 1) { if(($i+1) % $m == ...
- AD预测论文研读系列1
A Deep Learning Model to Predict a Diagnosis of Alzheimer Disease by Using 18F-FDG PET of the Brain ...