AJAX
AJAX概述
创建XHR实例
XHR即XMLHttpRequest。
标准方法是通过JavaScript的XHR对象发起异步请求,而IE浏览器专有办法是使用ActiveX控件。一旦创建,用于设置、发起和响应请求的代码就是相对的独立与浏览器的,并且创建XHR实例对于任何特定的浏览器都很简便。但是不同的浏览器实现方法不同,所以创建方法也不同。
var xhr;
if (window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}
else if (window.ActiveXObject){
xhr = new ActiveXObject("Msxml2.XMLHTTP");
}
else {
throw new Error("Ajax is not supported by this browser.");
}
创建之后,XHR实现跨越所有支持的浏览器实例,拥有一组方便可靠的属性和方法。
方法列表:
方法 | 描述 |
---|---|
abort() | 导致当前正在执行的请求被取消 |
getAllResponseHeader() | 返回一个字符串,包含所有相应标头的名称和值 |
getResponseHeader(name) | 返回指定的响应标头的值 |
open(method,url,async,username,password) | 设置请求的方法和目标URL,同步,认证用户名和口令三者是可选的 |
send(content) | 发起带有指定的体内容的请求,参数可选 |
setRequestHeader(name,value) | 利用指定的名称和值,设置一个请求标头 |
属性列表:
属性 | 描述 |
---|---|
onreadystatechange | 指派在请求的状态发生变化时所使用的事件处理程序 |
readyState | 一个整数值,指示请求的状态 0:未初始化 1:正在加载 2:已加载 3:交互 4:完成 |
responseText | 在响应里所返回的体内容 |
responseXML | 如果体内容为XML,就根据体内容创建XML DOM |
status | 从服务器所返回的响应状态码(200,404…) |
statusText | 响应所返回的状态文本消息(OK,not found) |
发起请求
发起请求之前,需要完成一些设置:
- 指定HTTP方法,GET/POST,并提供URL
- 让XHR实例知道如何通报进展
- 为POST请求提供合适的体内容
第一步,通过调用open()方法设置前两个参数:
xhr.open('GET','/some/resource/url');
这个方法还没有发送请求,只是设置,第三个参数决定是否异步,true为默认值表示异步,false为同步。
第二步,通过指派回调函数到onreadystatechange属性上来设置就绪状态处理程序,让XHR实例告知我们当前正在进行什么。通过查看XHR的其他属性,即可查明当前进行的处理。
第三步,通过send()方法为POST请求提供体内容并发送到服务器。
xhr.send(null);//GET方法没有体内容
xhr.send('a=1&b=2&c=3');//POST方法的体内容
跟踪进展
XHR实例通过就绪状态处理程序通知自身的进展。一旦通过send()方法发起请求,随着请求在不同状态之间的转换,这个回调函数会被调用多次。
举个例子:
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if(xhr.status >=200 && xhr.status<300){
//success
}
else {
//error
}
}
}
获得响应
就需处理程序确定readyState为已完成并且请求已成功地完成之后,就可以从XHR实例中获取响应体。
AJAX的响应不仅限于XML,还可以是普通文本,HTML片段,JSON,JS对象的文本表示。
AJAX的几大难点
- 初始化XHR对象需要特定于浏览器的代码
- 就绪处理程序必须过滤大量无趣的状态变化
- 就绪处理程序不会自动地获得引用以便调用XHR实例
- 响应体必须根据其格式以不同的方式来进行处理
加载内容到元素上
AJAX最常见的功能之一是从服务器获取一块内容并填充到DOM的指定位置上。
先对比一下原生JS和jQuery的实现办法:
//原生JS
var xhr;
if (window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}
else if (window.ActiveXObject){
xhr = new ActiveXObject("Msxml2.XMLHTTP");
}
else {
throw new Error("Ajax is not supported by this browser.");
}
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if(xhr.status >=200 && xhr.status<300){
document.getElementById('someId').innerHTML = xhr.responseText;
}
else {
//error
}
}
}
xhr.open('GET','/serverResource');
xhr.send();
//jQuery
$('#someId').load('/serverResource');
利用jQuery加载内容
load(url,parameters,callback)
有可选的参数,向指定的URL发起AJAX请求,可以指定回调函数,在请求完成时调用,响应文本可以替换为所有以匹配元素的内容。
参数 描述 url (字符串)服务器端资源的URL,请求的接收方 parameters (对象)一个对象,其属性被序列化为正确的编码的参数以便传递到请求里。如果指定就用POST方法,省略就用GET方法。 callback (函数)一个回调函数,在响应数据已经加载到包装集元素之后调用,传入这个函数的参数时响应文本、状态码、以及XHR实例 返回
包装集
load()函数需要有几点特别注意的地方,如果要发送带参数的GET请求,应当将参数写在URL后面,而不是parameters里面。如果要对返回的响应结果做筛选,可以给URL添加空格和#作为后缀来完成,后缀的后面紧接选择器。
$('.inject').load('/someResource #div');//筛选响应元素,只插入<div>实例
serialize()
根据包装集里所有的成功表单元素,创建正确格式化的经过URI编码的查询字符串
参数
无
返回
已格式化的查询字符串
成功表单元素是指根据HTML规范,作为表单提交的一部分而被包括的控件,未选中的复选框和单选按钮,未选择的下拉列表,禁用的控件都不包括在内。
serializeArray()
把所有的成功表单控件的值都收集到对象的数组中(包含名称和值)
参数
无
返回
表单数据的数组
返回的数组有匿名对象实例所组成,每一个均包含name和value属性。
发起GET和POST请求
GET请求:服务器的状态和应用的模型数据应该不受GET操作的影响,同样的GET操作无论执行多少次,结果都应当一致。
POST请求:发送到服务器的数据可以用来修改应用的模型状态,例如给数据库添加记录或是删除一些服务器的信息。
因此,GET请求应当用来获取数据,POST请求用于发送数据到服务器并实现一些修改
利用jQuery获取数据
$.get(url,parameters,callback)
利用指定的URL,带着任何已传入的参数作为查询字符串而向服务器发起GET请求
参数 描述 url (字符串)将要通过GET方法进行交互的服务器端资源的URL parameters (对象/字符串)一个对象,其属性作为”名称/值对”用于构造查询字符串并追加到URL,或者是一个预先格式化的并经过URI编码的查询字符串 callback (函数)回调函数,请求完成时被调用,响应体作为第一个参数,响应状态作为第二个参数传递给回调函数 返回
XHR实例
<script>
$(function(){
$('#test').click(function{
$.get(
'reflectData.jsp',
{a:1,b:1,c:1},
function(data){alert(data);}
);
});
});
</script>
如果响应包含一个XML文档,则文本会被解析,将解析后的DOM作为第一个参数传递给回调函数。
XML文档在层次结构上有其优势,但解析XML非常麻烦,另一种常用的文件格式为JSON。
$.getJSON(url,parameters,callback)
利用指定的URL,带着任何已传入参数作为查询字符串而向服务器发起GET请求,响应被解析为JSON字符串,伟作为结果的数据江北传递给回调函数。
参数 描述 url (字符串)将要通过GET方法进行交互的服务器端资源的URL parameters (对象/字符串)一个对象,其属性作为”名称/值对”用于构造查询字符串并追加到URL,或者是一个预先格式化的并经过URI编码的查询字符串 callback (函数)回调函数,请求完成时被调用,把响应体解析为JSON字符串并作为第一个参数,响应状态作为第二个参数传递给回调函数 返回
XHR实例
放一个《jQuery实战》中的例子,该例子设计了一个层叠下拉列表,style->color->size三层
<html>
<head>
<title>Welcome<title>
<link rel="stylesheet" type="text/css" href="boot.closet.css">
<script src="../../scripts/jquery-1.2.1.js"></script>
<script src="jquery.jqia.selects.js"></script>
<script src="jquery.jqia.termifier.js"></script>
<script>
$(function(){//主函数
$('#styleDropdown').change(function(){//当style下拉菜单的值发生改变
var styleValue = $(this).val();//获取当前style的值
$('#detailDisplay').load(//用AJAX在detailDisplay块中添加获取到的style详细信息
'getDetail.jsp',//目标URL为网站的getDetail.jsp
{style:styleValue},//参数
function(){//回调函数
$('abbr').termifier({lookupResource:'getTerm.jsp'});
}
);
adjustColorDropdown();//调用color下拉菜单的调整函数
}).change();//给style的下拉菜单绑定监听器
$('#colorDropdown').change(function(){adjustSizeDropdown();});//给color的下拉菜单绑定监听器
});
function adjustColorDropdown() {
var styleValue = $('#styleDropdown').val();//获取style值
var dropdownSet = $('#colorDropdown');//定义包装集变量,id="colorDropdown"
if (styleValue.length == 0){//判断style值是否为空,以确定是否禁用color下拉菜单
dropdownSet.attr("disabled",true);//禁用
dropdownSet.emptySelect();//清空内容
adjustSizeDropdown();//清空从属的下拉菜单的内容
}
else {
dropdownSet.attr("disabled",false);//启用
$.getJSON(//利用AJAX获得该style所对应的color下拉菜单的内容
'getColors.jsp',
{style:styleValue},
function(data){
dropdownSet.loadSelect(data);//将获取的内容放入color下拉菜单
adjustSizeDropdown();//启用size下拉菜单
}
);
}
}
function adjustSizeDropdown(){
var styleValue = $('#styleDropdown').val();//获取style值
var colorValue = $('#colorDropdown').val();//获取color值
var dropdownSet = $('#sizeDropdown');//定义包装集变量,id="sizeDropdown"
if ((styleValue.length == 0)||(colorValue.length == 0)) {//判断是否禁用
dropdownSet.attr("disabled",true);//禁用
dropdownSet.emptySelect();//清空内容
}
else {
dropdownSet.attr("disabled",false);//启用
$.getJSON(//利用AJAX获得该style和color所对应的size下拉菜单的内容
'getSizes.jsp',
{style:styleValue,color:colorValue},
function(data){
dropdownSet.loadSelect(data);//将获取的内容放入size下拉菜单
}
);
}
}
</script>
</head>
<body>
<form action="" id="orderForm">
<div id="detailFormContainer">
<div id="cascadingDropdown">
<div>
<label>Style:</label><br />
<select id="styleDropdown">
<option value="">Please choose a style</option>
<option value="111">style111</option>
<option value="222">style222</option>
<option value="333">style333</option>
</select>
</div>
<div>
<label>Color:</label><br />
<select id="colorDropdown" disabled="disabled">
</select>
</div>
<div>
<label>Size:</label><br />
<select id="sizeDropdown" disabled="disabled">
</select>
</div>
</div>
<div id="detailDisplay">
</div>
</div>
</form>
</body>
</html>
上述代码较为浅显地说明了jQuery的AJAX使用方法,当然还有两个命令(emptySelect和loadSelect)是需要自己完成的。
(funtion($){
$.fn.emptySelect = function(){
return this.each(function(){ if (this.tagName == 'SELECT') { this.options.length = 0; } });
}
$.fn.loadSelect = function(optionsDataArray){
return this.emptySelect().each(function(){ if (this.tagName == 'SELECT') { var selectElement = this; $.each(optionsDataArray,function(index,optionData){ var option = new Option(optionData.caption,optionData.value); if ($.browser.msie){ selectElement.add(options); } else{ selectElement.add(options,null) } }); } });
}
})(jQuery);
发起POST请求
$.post(url,parameters,callback)
利用指定的URL,带着任何已传入的参数作为查询字符串而向服务器发起POST请求
参数 描述 url (字符串)将要通过POST方法进行交互的服务器端资源的URL parameters (对象/字符串)一个对象,其属性作为”名称/值对”用于构造查询字符串并追加到URL,或者是一个预先格式化的并经过URI编码的查询字符串 callback (函数)回调函数,请求完成时被调用,响应体作为第一个参数,响应状态作为第二个参数传递给回调函数 返回
XHR实例
完全控制AJAX请求
上述方法已经可以完成很多AJAX的操作,但有时候希望亲手把握关键的细节,就需要更精细的参数设置。
细粒度控制的AJAX请求
$.ajax(options)
利用以传递的选项(控制如何生成请求以及如何通知回调函数)来发起AJAX请求。
参数 描述 options (对象)一个对象实例,其属性定义这个操作的参数,具体见下表 返回
XHR实例
$.ajax()的各种选项
名称 | 类型 | 描述 |
---|---|---|
url | 字符串 | 请求的URL |
type | 字符串 | 将要使用的HTTP方法,通常为GET或POST默认为GET |
data | 对象 | 其属性作为查询参数而传递给请求 如果是GET请求,则把数据作为查询字符串传递 如果是POST情趣,则把数据作为请求体传递 都是由$.ajax()来处理值的编码 |
dataType | 字符串 | 用于标识预期将被响应所返回的数据的类型 这个值决定在数据传递给回调函数前怎么处理 xml:响应文本被解析为XML文档,而作为结果的XML DOM被传递给回调函数 html:响应文本未经处理就被传递给回调函数,在已返回HTML片段内的任何 <script> 块将被求值json:响应文本被求值为JSON字符串,而作为结果的对象被传递给回调函数 jsonp:与json相似,不同之处是提供远程脚本支持 srcipt:响应文本被传递给回调函数,在任何回调函数被调用之前,响应被作为一个或多个JS语句处理 text:响应文本被假定为普通文本,服务器资源富则设置适当的内容类型响应标头 如果省略这个属性则不对响应文本进行任何处理或求值就传递给回调函数 |
timeout | 数值 | 设置AJAX 请求超时的毫秒数,如果在超时值到期之前仍未完成,则终止请求并且调用错误回调函数 |
global | 布尔型 | 启用(true)或禁用(false)所谓全局函数的触发,这些函数可以附加到元素上,并且在AJAX调用的不同时刻或状态下触发,如果省略默认启用 |
contentType | 字符串 | 将要在请求上指定的内容类型,如果省略,则默认为application/x-www-form-urlencoded(与表单提交所使用的默认类型相同) |
success | 函数 | 如果请求的响应指示成功状态码,则这个函数被调用,响应体作为第一个参数返回给这个参数,并且根据制定的dataType属性进行格式化,第二个参数式包含状态码的字符串——在这种情况下永远为成功状态码 |
error | 函数 | 如果请求的响应返回错误状态码,则这个函数被调用,三个实参被传递给这个函数:XHR实例,状态消息字符串(在这种情况下永远为错误状态码)以及XHR实例所返回的异常对象(可选) |
complete | 函数 | 在请求完成时被调用,两个实参被传递:XHR实例和状态消息字符串(成功状态码或错误状态码),如果也制定了success或error回调函数,则这个函数在success或error回调函数调用之后被调用 |
beforeSend | 函数 | 在发起请求之前被调用,这个函数被传递XHR实例,并且可以用来设置自定义的标头或执行其他预请求操作 |
async | 布尔型 | 如果指定为false则请求被提交为同步请求,在默认的情况下,请求是异步的 |
processData | 布尔型 | 如果设置为false则阻止已传递数据被加工为URL编码格式,默认情况下,数据被加工为URL编码格式 |
ifModified | 布尔型 | 如果设置为true,则从上一次请求以来,只有在响应内容没有改变的情况下(根据Last-Modified标头)才允许请求成功,如果省略,则不执行标头检查 |
通过$.ajaxSetup可以设置默认值,不必每次都写一长串参数。
$.ajaxSetup(properties)
为后续的$.ajax()调用,把传入的一组属性设置为默认值
参数 描述 properties (对象)其属性定义一组默认的AJAX属性,这些属性与上表所描述的相同
$.ajaxSetup({
type:'POST',
timeout:5000,
dataType:'html',
error:function(xhr){
$('#errorDisplay').html('Error: ' + xhr.status + ' ' + xhr.statusText);
}
})
这些默认值只会影响由$.ajax()
发起的AJAX请求,不包括load()
!
全局函数
利用$.ajaxSetup()
建立默认的函数,从而为所有的AJAX请求指定将被执行的默认函数。jQuery还支持把函数附加到特定的DOM元素,这些函数在AJAX请求处理的不同阶段或在请求最终成功或失败时触发。
例如:
$('#errorConsole').ajaxError(reportError);
会在任何AJAX请求失败的事件中调用reportError函数。
当全局函数被调用时,传递给回调参数的第一个参数有JS的Object实例构成,包含下列两个属性:
- type:包含全局函数的类型字符串,如ajaxError
- target:DOM元素被附加了全局函数的引用,在前面的例子中即为id=”errorConsole”的元素
这个构造称为全局回调信息对象,这个参数用来标识什么全局函数类型触发了回调函数以及全局函数被附加到了哪个元素上。
ajaxStart(callback)
ajaxSend(calback)
ajaxSuccess(callback)
ajaxError(callback)
ajaxComplete(callback)
ajaxStop(callback)
把传入的回调函数附加到所有匹配元素上,一旦到达AJAX请求处理的指定时刻就触发回调函数
参数 描述 callback (函数)将被附加的回调函数 返回
包装集
全局函数类型 | 触发时机 | 参数 |
---|---|---|
ajaxStart | 在AJAX命令发起时,但在XHR实例被创建之前 | 类型被设置为ajaxStart的全局回调信息对象 |
ajaxSend | 在XHR实例被创建之后,但在XHR实例被发送给服务器之前 | 类型被设置为ajaxSend的全局回调信息对象,XHR实例:$.ajax()函数使用的属性 |
ajaxSuccess | 在请求已从服务器返回之后,并且包含成功状态码 | 类型被设置为ajaxSuccess的全局回调信息对象,XHR实例:$.ajax()函数使用的属性 |
ajaxError | 在请求已从服务器返回之后,并且包含失败状态码 | 类型被设置为ajaxError的全局回调信息对象,XHR实例:$.ajax()函数使用的属性,被XHR实例返回的异常对象 |
ajaxComplete | 在请求已从服务器返回之后,并且在任何已声明的ajaxSuccess或ajaxError回调函数已被调用之后 | 类型被设置为ajaxComplete的全局回调信息对象,XHR实例:$.ajax()函数使用的属性 |
ajaxStop | 在所有其他AJAX处理完成以及任何其他适用的全局回调函数已被调用之后 | 类型被设置为ajaxStop的全局回调信息对象 |
<html>
<head>
<title>Test<title>
<script src="../../scripts/jquery-1.2.1.js"></script>
<script>
$('#goodButton').click(function(){
$.get('reflectData.jsp');
});
$('#badButton').click(function(){
$.get('reflectError.jsp');
});
$('#successDisplay').ajaxSuccess(function(info){
$(info.target).append('<div>Success at '+new Date()+'</div>');
});
$('#errorDisplay').ajaxError(function(info.xhr){
$(info.target)
.append('<div>Failed at '+new Date()+'</div>')
.append('<div>Status: '+xhr.status+' '+xhr.statusText+'</div>');
});
</script>
</head>
<body>
<fieldset>
<legend>Button Area</legend>
<div>
<button type="button" id="goodButton">
GOOD
</button>
<button type="button" id="badButton">
BAD
</button>
</div>
</fieldset>
<fieldset>
<legend>Success Area</legend>
<div id="successDisplay"></div>
</fieldset>
<fieldset>
<legend>Error Area</legend>
<div id="errorDisplay"></div>
</fieldset>
</body>
</html>