文章目录
全称
- Asynchronous JavaScript And XML,即异步 JavaScript 和 XML
流程
- 浏览器通过 JavaScript 代码向服务器发送请求,JavaScript 代码负责解析服务器的响应数据,并把样式表加到数据上,然后在现有网页中显示出来
- Ajax 使用 XMLHttpRequest 对象异步发送请求(不再直接向服务器提交),并且发送请求时不要求重新加载页面,浏览器发送请求后,无须等待服务器响应,而是可以继续原来的操作,在服务器的响应完成后,客户端使用 JavaScript 函数将响应数据加载到浏览器中,这样从请求到响应的这个过程就在后台进行,而不会中断用户的其它操作(异步发送请求,动态加载服务器响应数据)
优势
- 最大优势在于异步交互,即浏览者在浏览页面时,可同时向服务器发送请求,甚至可以不用等待前一次请求得到完全响应,便再次发送请求,这种异步请求的方式,非常类似于传统的桌面应用
- Ajax 将请求与页面分离:在传统的 Web 应用里,每个请求对应一个页面,不管客户端以
POST
还是GET
方式提交请求,每次请求都会丢失当前页面,等待服务器生成新页面。在等待期间,旧的页面已经丢弃,新的页面还没有完全生成,整个浏览器将一片空白,而用户什么都做不了,只能等待
核心
- Ajax 的核心是 JavaScript 对象 XMLHttpRequest,该对象在 IE5 中首次引入,它提供了异步发送请求的能力
XMLHttpRequest 对象详解
XMLHttpRequest 对象的方法
-
abort()
:停止发送当前请求 -
getAllResponseHeaders()
:获取服务器返回的全部响应头 -
getResponseHeader("headerLabe")
:根据响应头的名字,获取对应的响应头 -
open("method","URL"[,asyncFlag[,"userName"[,"password"]]])
:建立与服务器 URL 的连接,并设置请求的方法,以及是否使用异步请求。如果远程服务需要用户名、密码, 则提供对应的信息 -
send(content)
:发送请求,其中 content 是请求参数 -
setRequestHeader("label", "value")
:在发送请求之前,先设置请求头
XMLHttpRequest 对象的属性
-
onreadystatechange
:该属性用于指定 XMLHttpRequest 对象状态改变时的事件处理函数,当 XMLHttpRequest 对象的状态改变时,该函数将被触发XMLHttpRequest 对象有如下几种状态:
0
: XMLHttpRequest 对象还没有完成初始化
1
: XMLHttpRequest 对象开始发送请求
2
: XMLHttpRequest 对象的请求发送完成
3
: XMLHttpRequest 对象开始读取服务器的响应
4
: XMLHttpRequest 对象读取服务器响应结束
XMLHttpRequest 对象的这几种状态信息可通过 readyState 属性读取,因此可以这样理解:每当 XMLHttpRequest 对象的 readyState 属性改变时,其 onreadystatechange 属性指定的方法都会被触发
【个人理解】在状态 2 和状态 3 之间还存在这样一个过程:当 XMLHttpRequest 对象的请求发送完成后,程序转到服务器端执行,在服务器端执行完成后,程序又返回到 XMLHttpRequest 对象处,然后 XMLHttpRequest 对象开始读取服务器的响应 -
readyState
:该属性用于获取 XMLHttpRequest 对象的处理状态(0 — 4) -
responseText
:该属性用于获取服务器的响应文本 -
responseXML
:该属性用于获取服务器响应的XML文档对象 -
status
:该属性是服务器返回的状态码,只有当服务器的响应已经完成时,才会有该状态码
服务器常用的状态码及对应的含义:
200
:服务器响应正常
304
:该资源在上次请求之后没有任何修改。这通常用于浏览器的缓存机制,使用GET 请求时尤其需要注意
400
:无法找到请求的资源
401
:访问资源的权限不够
403
:没有权限访问资源
404
:需要访问的资源不存在
405
:需要访问的资源被禁止
407
:访问的资源需要代理身份验证
414
:请求的URL太长
500
:服务器内部错误 -
statusText
:该属性是服务器返回的状态文本信息,只有当服务器的响应已经完成时,才会有该状态文本信息500 对应的文本信息为:Internal Server Error
200 对应的文本信息为:OK
【小结】如果想通过 JavaScript 获取服务器响应,必须先判断服务器响应是否完成。要判断服务器的响应是否完成,只需判断 XMLHttpRequest 对象的 readyState 属性即可,当 readyState 值为 4 时,代表响应完成;服务器响应完成后,还应判断服务器响应是否正确,要判断服务器响应是否正确,可通过判断XMLHttpRequest 对象的 status 属性进行。当 status 的值为 200 时,服务器响应正确,否则响应不正常
发送请求
- Ajax 与传统 Web 应用的第一个区别在于发送请求的方式不同:传统 Web 应用采用表单或请求某个资源的方式发送请求;而 Ajax 则采用异步方式在后台发送请求。下面我们将详细介绍 Ajax 发送请求的各种细节
发送简单请求
-
所谓简单请求,是指不包含任何参数的请求(这里的参数指的是请求响应的 URL 中的参数)
-
因为无须发送请求参数,所以采用 POST 和 GET 方式并没有太大区别,但不管以哪种方式发送请求,XMLHttpRequest 都应该按如下步骤进行:
- 初始化 XMLHttpRequest 对象
<script type="text/javascript">
// XMLHttpRequest 对象
var xmlrequest;
//创建 XMLHttpRequest 对象的初始化函数
function createXMLHttpRequest() {
if (window.XMLHttpRequest) {
// DOM2 浏览器
xmlrequest = new XMLHttpRequest();
} else if (window.ActiveXObject) {
// IE 浏览器
try {
xmlrequest = new ActiveXObject("HMsxml2.XMLHTTPM");
} catch (e) {
try {
xmlrequest = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
}
}
}
}
</script>
【注】:
1、这里只是写了如何创建 XMLHttpRequest 对象,但还没有创建,需要创建的时候只要调用 createXMLHttpRequest()
这个函数就行
2、因为这里要分开讲解,为了避免出错,所以在最后把这部分代码用 script
标签包起来了,但其实整个流程的代码也可以只放在这一个 script
标签里面
- 打开与服务器的连接。打开连接时,指定发送请求的方法:采用 GET 或POST;指定是否采用异步方式(true 表示异步)
- 设置监听 XMLHttpRequest 状态改变的事件处理函数
- 发送请求。如采用 POST 方法发送请求,可发送带参数的请求
<script type="text/javascript">
function sendRequest() {
// 初始化 XMLHttpRequest 对象
createXMLHttpRequest();
// 定义发送请求的目标的 URL,这里展示的是未带参数的 URL
var url = second.jsp;
// 打开与服务器的连接
xmlrequest.open("POST”, url, true);
// 指定当 XMLHttpRequest 状态改变时的事件处理函数
xmlrequest.onreadystatechange = processResponse;
// 发送请求
xmlrequest.send(null);
}
//当 XMLHttpRequest 状态改变时,该函数将被触发
function processResponse() {
if(xmlrequest.readyState == 4) {
if(xmlrequest.status == 200) {
// 这里是自己具体的业务逻辑操作
}
}
}
</script>
【特别注意】:
- 上面的代码虽然定义了发送请求的函数
sendRequest()
,但是并没有写该何时发送请求,也就是在何时何地调用该函数,因为我们没有指定具体的场景和需求 - 可能
sendRequest()
这个函数需要隔一段时间就被调用一次(设置定时器)亦或是在发生点击事件时调用(此时sendRequest()
这个函数应该绑定点击事件)甚至是在页面加载时就需要调用(给body
标签指定"sendRequest();"
)等等,还可能是多者的结合,需要在具体场景中灵活使用 - open() 方法通常有三个参数:第一个参数指定发送请求的方式——只能是 POST 或 GET,通常建议采用 POST 方式;第二个参数指定发送请求的服务器资源的地址;第三个参数只能为 true 或 false,用于指定是否采用异步方式发送请求
发送GET请求
- GET 请求将所有请求参数转换成一个查询字符串,并将该字符串添加到请求的 URL 之后,因而可在请求的 URL 后看到请求参数名、请求参数值。如果将某个表单的 action 属性设置为 GET,则请求会将表单中各字段的名和值转换成字符串,并附加到 URL 之后
- 虽然 GET 请求的请求参数是附加在 URL 之后的,但使用 send() 方法时,还是应该为 send() 方法传入参数。如果调用 send() 方法时无须发送请求参数,则使用 null 作为参数即可。如果直接使用 send() 方法,不传入任何参数(包括 null),则在 Internet Explorer 中可以运行,而在 Firefox 中将不能正常运行
发送POST请求
- 发送 POST 请求通常需要如下三个步骤:
- 使用 open() 方法打开连接时,指定使用 POST 方式发送请求
- 设置正确的请求头,POST 请求通常应设置 Content-Type请求头
- 发送请求,把请求参数转为查询字符串,将该字符串作为 send() 方法的参数
-
事实上,即使采用 POST 方式发送请求,一样可以将请求参数附加在请求的 URL 之后
-
类似于 GET 请求的是,即使没有请求参数,在调用 send() 方法时,也一定要为 send() 方法传入 null 参数,因为 Firefox 等浏览器要求调用 send() 方法时必须传入参数
发送请求时的编码问题
-
对于亚洲开发者而言,不可避免地需要发送包含非西欧字符(如汉字符、韩字符)的请求参数,而这些请求参数在传输过程中的编码将直接影响服务器的处理。当然,如果发送的请求里不包含非西欧字符,将不会有任何问题,但一旦包含了非西欧字符的请求参数,则可能出现异常。对我们来说,其实就是解决中文乱码的问题
-
在很多时候,当我们使用了非西欧字符时,使用 POST 方式不会出现乱码,而使用 GET 方式会出现乱码,因此通常建议发送 POST 请求,尽量少使用 GET 请求,还有如下的几个理由:
- 处理 GET 请求的请求参数比较烦琐
- 当请求参数包含的数据太多时,GET 请求可能丢失请求参数
- 当两次 GET 请求的请求参数相同时,Internet Explorer 将直接使用服务器上次的缓存,根本不会重新发送请求,这对于自动刷新页面相当不利
对于 Internet Explorer 会“自作聪明”地缓存服务器响应的问题,开发 Ajax 应用时确实比较烦琐,不过有一个方法对付:不管我们是否需要发送请求参数,发送 Ajax 请求时总是额外地增加一个参数,参数随意,参数值使用当前时间——这样就可以保证每次请求都有不同的请求参数,而 Internet Explorer 就会再次发送请求了
处理服务器响应
- 完整的异步通信包括发送请求、与服务器交互和获取服务器响应三个步骤。当服务器获得客户端请求参数后,开始处理。服务器处理结束并生成响应后,客户端必须获得服务器响应,并对服务器响应进行处理,将响应动态加载在当前页面上。
处理的时机
-
获得服务器的响应很简单,主要依赖于两个属性:responseText 和 responseXML。当然, 并不是任意时刻调用XMLHttpRequest对象的这两个属性都可以获取服务器响应。如果服务器响应还没有结束,或者没有生成正确的响应,则调用这两个属性将不能获取正确的响应
-
在 XMLHttpRequest 与服务器的通信过程中,XMLHttpRequest 对象的 readyState 属性可动态监控服务器的响应,当 XMLHttpRequest 的 readyState 值为 4 时,表明服务器的响应已经完成
-
服务器响应完成后,还需要判断响应是否正确,这可借助于 XMLHttpRequest 对象的 status 属性,该属性代表服务器响应的状态码。前面已经介绍过,服务器响应正确的状态码为 200;如果没有发送请求,而是直接从浏览器缓存读取响应,则状态码为 304。由此可见,当 readyState 等于 4,且 status 状态码为 200 或 304 时,客户端就可以开始处理服务器的响应了。因此在 Ajax 应用中常常可以见到如下代码片段:
//判断处理服务器响应的时机是否成熟 if (objXMLHttp.readyState == 4 && (objXMLHttp.status == 200 || objXMLHttp.status == 304)) { }
使用文本响应
-
一旦处理服务器响应的时机成熟,就可以获取服务器响应了。获取服务器响应主要借助于 XMLHttpRequest 对象的如下两个属性:
responseText
:生成普通文本响应,将返回服务器响应的字符串。
responseXML
:生成 XML 响应【注意】
- 使用文本响应适用于响应简单字符串的情形。在这种情形下,服务器响应的是普通文本内容,基本不会包含太多格式。如果需要对文本字符串进行处理,则客户端需要自己分析该字符串
使用JSON响应
- 如果服务器需要生成特别复杂的响应,则可采用生成 XML 响应。生成 XML 响应需要借助于 XMLHttpRequest 的 responseXML 属性,该属性生成一个 XML 文档对象
- 几乎所有的浏览器都提供了解析 XML 文档对象的方法,借助于浏览器解析 XML 文档的能力,JavaScript 可以访问到 XML 文档的节点值,一旦访问到 XML 文档的节点值,就可以通过 DOM 动态加载到页面中显示出来
- 早期 Ajax 技术曾经大量使用 XML 响应,但随着 JSON 技术的广泛应用,使用 XML 响应的缺点逐渐凸显。使用 XML 响应主要有如下缺点:
- 同样的数据,转换为XML格式比转换为JSON格式的数据量更大
- 使用 XML 响应必须在服务器端生成符合XML格式的字符串,编程复杂
- 浏览器获取 XML 响应之后,需要使用 DOM 解析 XML 响应,编程复杂
- 当服务器向浏览器生成符合 JSON 格式的字符串以后,浏览器端需要解析该 JSON 字符串,将它解析成 JavaScript 对象或 JavaScript 数组。 一旦将服务器响应数据转换成 JavaScript 对象或 JavaScript 数组,接下来只要使用 DOM 将响应显示出来即可
使用 JavaScript 内置的 eval() 函数解析 JSON 格式的字符串可能有一些潜在的 安全问题,为了避免 eval() 函数导致的问题,可以使用一些更安全的 JavaScript 库 (如 Prototype )提供的函数来解析 JSON 字符串
总结
- Ajax 技术的整个过程如下:XMLHttpRequest 发送请求,在与服务器交互的过程中,其 readyState 状态可以监听到服务器的响应状态;当服务器的响应完成时, XMLHttpRequest 负责解析服务器响应;获取到响应后,解析出响应的数据,通过 DOM 操作来加载服务器响应