AJAX 全稱 Asynchronous JavaScript and XML(異步的 JavaScript 和 XML)。它並不是一種新的技術,而是如下幾種原有技術的結合體。javascript
1) 使用CSS和XHTML來表示。php
2) 使用DOM模型來交互和動態顯示。html
3) 使用XMLHttpRequest來和服務器進行異步通訊。html5
4) 使用javascript來綁定和調用。java
經過AJAX異步技術,能夠在客戶端腳本與web服務器交互數據的過程當中使用XMLHttpRequest對象來完成HTTP請求(Request)/應答(Response)模型:jquery
1) 不須要用戶等待服務端響應。在異步派發XMLHttpRequest請求後控制權立刻就被返回到瀏覽器。界面不會出現白板,在獲得服務器響應以前還能夠友好的給出一個加載提示。web
2) 不須要從新加載整個頁面。爲XMLHttpRequest註冊一個回調函數,待服務器響應到達時,觸發回調函數,而且傳遞所需的少許數據。「按需取數據」也下降了服務器的壓力。ajax
3) 不須要使用隱藏或內嵌的框架。在XHR對象以前,模擬Ajax通訊一般使用hack手段,如使用隱藏的或內嵌的框架(<iframe>標籤)。正則表達式
下面介紹下AJAX中的重要對象:XMLHttpRequest。編程
XMLHttpRequest對象(XHR)
XMLHttpRequest是一套能夠在Javascript、VbScript、Jscript等腳本語言中經過http協議傳送或接收XML及其餘數據的一套API。
XMLHttpRequest對象首次以ActiveX對象形式在微軟Internet Explorer(IE) 5中以引入。其餘瀏覽器製造商在認識到這一對象重要性後也紛紛實現了XMLHttpRequest對象,可是以一個本地JavaScript對象而不是做爲一個ActiveX對象實現。而現在,因爲安全性、標準等問題,微軟已經在其IE 7中把XMLHttpRequest實現爲一個本地JavaScript對象。
API |
描述 |
||||||||||||||
客服端請求 |
|||||||||||||||
open(method,url,async, bstrUser, bstrPassword) |
規定請求的類型、URL 以及是否異步處理請求。 1) method:請求的類型,例如:POST、GET、PUT及PROPFIND。大小寫不敏感。 2) url:請求的URL地址,能夠爲絕對地址也能夠爲相對地址。 3) async[可選]:true(默認,異步)或 false(同步)。 註釋:當您使用async=false 時,JavaScript 會等到服務器響應就緒才繼續執行。若是服務器繁忙或緩慢,應用程序會掛起或中止。此時,不須要編寫onreadystatechange回調函數,把代碼放到 send()語句後面便可。 4) bstrUser[可選]:若是服務器須要驗證,此處指定用戶名,若是未指定,當服務器須要驗證時,會彈出驗證窗口。 5) bstrPassword[可選]:驗證信息中的密碼部分,若是用戶名爲空,則此值將被忽略。 |
||||||||||||||
getRequestHeader(name) |
獲取指定的相應頭部信息 |
||||||||||||||
setRequestHeader(name,value) |
自定義HTTP頭部信息。需在open()方法以後和send()以前調用,才能成功發送請求頭部信息。 傳送門:HTTP 頭部詳解
默認狀況下,服務器對POST請求和提交Web表單不會一視同仁,將Content-Type頭部信息設置爲application/x-www-form-urlencoded (模擬表單提交) |
||||||||||||||
send(string) |
將請求發送到服務器。參數string僅用於POST請求;對於GET請求的參數寫在url後面,因此string參數傳遞null。 |
||||||||||||||
abort() |
調用此方法可取消異步請求,調用後,XHR對象中止觸發事件,不容許訪問任何與響應相關的屬性; |
||||||||||||||
服務端響應 |
|||||||||||||||
onreadystatechange事件 |
對於異步請求,若是須要對服務器獲取和操做響應結果,則在send() 以前,須要爲onreadystatechange屬性指定處理方法。該函數用於對服務器響應進行處理。 |
||||||||||||||
readyState |
存有XMLHttpRequest的狀態。每當readyState改變時,就會觸發onreadystatechange事件。 從 0 到 4 發生變化:
|
||||||||||||||
status(數字表示) |
返回當前請求的http狀態碼。 傳送門:HTTP狀態碼一覽表(HTTP Status Code)
|
||||||||||||||
statusText(字符表示) |
返回當前請求的狀態文本eg:OK (status:200) |
||||||||||||||
responseText |
將響應信息做爲字符串返回 |
||||||||||||||
responseXML |
將響應信息格式化爲Xml Document對象並返回 |
||||||||||||||
responseBody(只有微軟的IE支持) |
將響應信息正文以unsigned byte數組形式返回(二進制數據) |
||||||||||||||
responseStream(只有IE的某些版本支持) |
以Ado Stream對象(二進制流)的形式返回響應信息 |
||||||||||||||
getResponseHeader(name) |
從響應信息中獲取指定的http頭 |
||||||||||||||
getAllResponseHeaders() |
獲取響應的全部http頭 |
||||||||||||||
overrideMimeType |
一般用於重寫服務器響應的MIME類型。Eg,正常狀況下XMLHttpRequest只接收文本數據,但咱們能夠重寫MIME爲「text/plain; charset=x-user-defined」,以欺騙瀏覽器避免瀏覽器格式化服務器返回的數據,以實現接收二進制數據。 |
一個簡單的ajax封裝:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
var
myAjax = {
// XMLHttpRequest IE7+, Firefox, Chrome, Opera, Safari ; ActiveXObject IE6, IE5
xhr: window.XMLHttpRequest ?
new
XMLHttpRequest() :
new
ActiveXObject(
'Microsoft.XMLHTTP'
),
get:
function
(url, callback) {
this
.xhr.open(
'get'
, url);
this
.onreadystatechange(callback,
this
.xhr);
this
.xhr.send(
null
);
},
post:
function
(url, data, callback) {
this
.xhr.open(
'post'
, url);
this
.xhr.setRequestHeader(
'Content-Type'
,
'application/x-www-form-urlencoded'
);
this
.onreadystatechange(callback,
this
.xhr);
this
.xhr.send(data);
},
onreadystatechange:
function
(func, _xhr) {
_xhr.onreadystatechange =
function
() {
if
(_xhr.readyState == 4) {
if
(_xhr.status == 200) {
func(_xhr.responseText);
}
}
}
}
}
|
使用:
1
2
3
4
5
6
7
8
9
|
$(
'#btn_nowTime1'
).bind(
'click'
,
null
,
function
() {
myAjax.post(
'AjaxHandler.ashx'
,
'func=GetServerTime'
,
function
(data) {
if
(data)
alert(data);
}
);
});
|
XMLHttpRequest Level 2
XMLHttpRequest是一個瀏覽器接口,使得Javascript能夠進行 HTTP (S) 通訊。可是,這個接口一直沒有標準化,每家瀏覽器的實現或多或少有點不一樣。HTML 5 的概念造成後,W3C 開始考慮標準化這個接口。2008年 2 月,提出了XMLHttpRequest Level 2 草案。
老版本的XMLHttpRequest對象有如下幾個缺點:
1) 只支持文本數據的傳送,沒法用來讀取和上傳二進制文件。
2) 傳送和接收數據時,沒有進度信息,只能提示有沒有完成。
3) 受到"同域限制"(Same Origin Policy),只能向同一域名的服務器請求數據。
新版本的XMLHttpRequest對象,針對老版本的缺點,作出了大幅改進。
1) 能夠設置 HTTP 請求的時限。
2) 可使用FormData對象管理表單數據。
3) 能夠上傳文件。
4) 能夠請求不一樣域名下的數據(跨域資源共享,Cross-origin resource sharing,簡稱 CORS)。
5) 能夠獲取服務器端的二進制數據。
6) 能夠得到數據傳輸的進度信息。
超時時限 |
|
timeout |
設置ajax請求超時時限,過了這個時限,就自動中止 HTTP請求。 |
ontimeout事件 |
當ajax超過timeout 時限時觸發的回調函數。 |
指定響應格式 |
|
responseType |
(默認:「text」)在發送請求前,根據您的數據須要,將xhr.responseType設置爲「text」、「arraybuffer」、「blob」或「document」。 |
response |
成功發送請求後,xhr的響應屬性會包含DOMString、ArrayBuffer、Blob 或 Document 形式(具體取決於responseTyp的設置)的請求數據。 |
進度信息 |
|
progress 事件 |
在XMLHttpRequest對象傳遞數據的時候用來返回進度信息。它分紅上傳和下載兩種狀況。下載的 progress 事件屬於XMLHttpRequest對象,上傳的 progress 事件屬於XMLHttpRequest.upload對象。即: xhr.onprogress = updateProgress; xhr.upload.onprogress = updateProgress; XHR還新增了與progress事件相關的五個事件: 1) load 事件:傳輸成功完成。 2) abort 事件:傳輸被用戶取消。 3) error 事件:傳輸中出現錯誤。 4) loadstart事件:傳輸開始。 5) loadEnd事件:傳輸結束,可是不知道成功仍是失敗。 |
1) 接收二進制數據(方法A:改寫MIMEType)
老版本的XMLHttpRequest對象,只能從服務器取回文本數據。但咱們能夠改寫數據的MIMEType,將服務器返回的二進制數據假裝成文本數據,而且告訴瀏覽器這是用戶自定義的字符集。
關鍵代碼以下:
服務端
1
2
3
4
5
6
7
8
9
10
11
|
String str =
"二進制數據獲取"
;
MemoryStream _memory =
new
MemoryStream();
BinaryFormatter formatter =
new
BinaryFormatter();
formatter.Serialize(_memory, str);
_memory.Position = 0;
byte
[] read =
new
byte
[_memory.Length];
_memory.Read(read, 0, read.Length);
_memory.Close();
context.Response.ContentType =
"text/plain"
;
// 服務器使用OutputStream輸出二進制流
context.Response.OutputStream.Write(read, 0, read.Length);
|
客服端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
$(
'#btn_mime'
).bind(
'click'
,
null
,
function
() {
$.ajax(
'AjaxHandler.ashx?func=GetBinaryData'
,
{
type:
'get'
,
dataType:
'text'
,
cache:
false
,
mimeType:
'text/plain; charset=x-user-defined'
,
success:
function
(data) {
if
(data) {
var
byte = [];
for
(
var
i = 0, len = data.length; i < len; ++i) {
var
c = data.charCodeAt(i);
byte[byte.length] = c & 0xff;
}
alert(byte);
}
}
});
});
|
瀏覽器會把相應數據當作文本數據接收,因此咱們還必須再一個個字節地還原成二進制數據。位運算"c & 0xff",表示在每一個字符的兩個字節之中,只保留後一個字節,將前一個字節扔掉。緣由是瀏覽器解讀字符的時候,會把字符自動解讀成Unicode 的 0xF700-0xF7ff區段。
截圖以下:(測試環境:google Chrome 版本 26.0.1410.43)
服務器端返回二進制數據:
客服端輸出:
a) 使用mimeType: 'text/plain; charset=x-user-defined'參數。
b) 沒有對服務器的MIME類型進行重寫,致使返回信息被瀏覽器格式化後輸出的二進制數據與服務器不一樣。而且不一樣瀏覽器格式化後輸出的二進制數據都有差別。
2) 接收二進制數據(方法B:responseType屬性)
在XMLHttpRequest Level2中,可使用新增的responseType屬性從服務器取回二進制數據。把responseType設爲 blob,表示服務器傳回的是二進制對象。
1
2
3
|
var
xhr =
new
XMLHttpRequest();
xhr.open (
'GET'
,
'/path/to/image.png'
);
xhr.responseType =
'blob'
;
|
接收數據的時候,用瀏覽器自帶的 Blob 對象便可。注意,讀取的xhr.response,而不是xhr.responseText。
1
|
var
blob =
new
Blob ([xhr.response], {type:
'image/png'
});
|
還能夠將responseType設爲arraybuffer,把二進制數據裝在一個數組裏。而後再遍歷這個數組。
1
2
3
4
5
6
7
8
9
10
|
var
xhr =
new
XMLHttpRequest ();
xhr.open (
'GET'
,
'/path/to/image.png'
);
xhr.responseType =
"arraybuffer"
;
var
arrayBuffer = xhr.response;
if
(arrayBuffer) {
var
byteArray =
new
Uint8Array (arrayBuffer);
for
(vari = 0; i<byteArray.byteLength; i++) {
// do something
}
}
|
2) XMLHttpRequest Level 2 使用指南
jQuery框架的Ajax
jQuery是一個快速、簡單的JavaScript library,核心理念是write less,do more(寫的更少,作的更多)。它簡化了HTML 文件的traversing,事件處理、動畫、Ajax 互動,從而方便了網頁製做的快速發展。jQuery是爲改變你編寫JavaScript 的方式而設計的。更多jQuery科普知識請看:jQuery百度百科(Eg:模塊,歷史版本)
下面介紹下jQuery框架中ajax相關API:
版本Jquery-1.7.1.js。
經過 HTTP 請求加載遠程數據。
返回值:$.ajax() 返回jqXHR對象(jqXHR對象:爲XMLHttpRequest對象的超集)。可用於手動終止請求abort()、爲ajax函數設置額外的回調函數等。
ajax內部實現的兩個重要對象:s對象和jqXHR對象。
1) s對象
由默認設置jQuery.ajaxSettings對象、options參數集合和jQuery.ajaxSetup({})默認設置合併而成s對象。
參數名 |
描述 |
|||||||||||||
可由ajax的options參數設置 |
||||||||||||||
url |
(默認: 當前頁地址) 要請求的目的URL地址。 |
|||||||||||||
username password |
用於響應HTTP訪問認證請求的用戶名及密碼 |
|||||||||||||
type |
(默認: "GET") 請求方式 ("POST" 或 "GET")。注意:其它 HTTP 請求方法,如 PUT 和 DELETE 也可使用,但僅部分瀏覽器支持。 |
|||||||||||||
dataType |
預期服務器返回的數據類型。若是不指定,jQuery將自動根據 HTTP 包 MIME 信息來智能判斷,好比 XML MIME 類型就被識別爲 XML。隨後服務器端返回的數據會根據這個值解析後,傳遞給回調函數。 必須確保網頁服務器報告的 MIME 類型與咱們選擇的dataType所匹配。好比說,XML的話,服務器端就必須聲明 text/xml 或者 application/xml 來得到一致的結果。 可用值:
其中,text 和 xml 類型返回的數據不會通過處理。數據僅僅簡單的將XMLHttpRequest的responseText或responseHTML屬性傳遞給 success 回調函數。 若是指定了 script 或者jsonp類型,那麼當從服務器接收到數據時,其實是用了<script>標籤而不是XMLHttpRequest對象。這種狀況下,$.ajax() 再也不返回一個XMLHttpRequest對象,而且也不會傳遞事件處理函數,好比beforeSend。 |
|||||||||||||
contentType |
(默認: "application/x-www-form-urlencoded")標明發送或者接收的實體的MIME類型。當「非GET或HEAD請求」的HTTP請求時,會被設置爲HTTP頭請求信息。 |
|||||||||||||
mimeType |
多用途互聯網郵件擴展(MIME,Multipurpose Internet Mail Extensions);用於重寫服務器端響應的MIME類型。 |
|||||||||||||
data |
發送到服務器的數據。能夠是一個查詢字符串,好比 key1=value1&key2=value2 ,也能夠是一個映射,好比 {key1: 'value1', key2: 'value2'} 。若是使用了後者的形式,則數據在發送前會經過jQuery.param()函數轉換成查詢字符串。這個處理過程也能夠經過設置processData選項爲false來回避。 |
|||||||||||||
processData |
(默認: true) 默認狀況下,發送到服務器的數據(即data參數)將被轉換爲字符串以配合默認內容類型"application/x-www-form-urlencoded"。若是要發送 DOM 樹信息或其它不但願轉換的信息,請設置爲false。 jQuery中的處理方式:
|
|||||||||||||
async |
(默認: true) 默認設置下,全部請求均爲異步請求。若是須要發送同步請求,請將此選項設置爲 false。注意,同步請求將鎖住瀏覽器,用戶其它操做必須等待請求完成才能夠執行。 |
|||||||||||||
timeout |
設置請求超時時間(毫秒)。經過setTimeout(fn,time)實現。 |
|||||||||||||
cache |
(默認: true)dataType爲 script 和jsonp時默認爲 false。設置爲 false 將不緩存此頁面。 當使用GET或HEAD方式發送請求時要添加時間戳參數 (net Date()).getTime() 來保證每次發送的URL不一樣, 能夠避免瀏覽器緩存.(只有GET和HEAD方式的請求瀏覽器纔會緩存) jQuery中的處理方式:
示例:/AjaxHandler.ashx?func=GetBinaryData&_=1368424995535 |
|||||||||||||
ifModified |
(默認: false) 僅在服務器數據改變時獲取新數據。經過響應頭If-Modified-Since、IF-None-Match和請求頭Last-Modified、Etag提升GET或HEAD方式請求效率。(只有GET和HEAD方式的請求瀏覽器纔會緩存) |
|||||||||||||
global |
(默認: true) 是否觸發全局 AJAX 事件。設置爲 false 將不會觸發全局AJAX 事件:ajaxStart、ajaxSend、ajaxSuccess、ajaxError、ajaxComplete、ajaxStop。(好比請求頻繁時可禁用全局AJAX事件提升效率) |
|||||||||||||
context |
(默認:true) 這個對象用於設置Ajax相關回調函數的上下文,讓回調函數內this指向這個對象。若是不設定這個參數,那麼回調函數中的this就指向調用本次AJAX請求時傳遞的options參數載體「s對象」。但對於全局Ajax事件來講,this都是指向全局事件所綁定的元素。 |
|||||||||||||
jsonp |
指定得到jsonp回調函數名的參數名(默認爲:callback)。這個值用來替代URL中"callback=?"裏的"callback"部分,好比{jsonp:'onJsonPLoad'}會替換爲將"onJsonPLoad=?"傳給服務器。 |
|||||||||||||
jsonpCallback |
爲jsonp請求指定一個回調函數名。jsonpCallback參數通常爲字符串,也可接收函數(該函數返回字符串)。 默認狀況下生成隨機函數名:"jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ) + jQuery.now() |
|||||||||||||
crossDomain |
(默認:null)false:同域請求;true跨域請求。 假若crossDomain標識爲null,則jQuery會自動根據本地url、端口來解析。能夠根據需求直接賦值來提升性能。 一般狀況下由服務器自動解析便可,但若是你想在同一域中強制跨域請求(像JSONP同樣),那麼將crossDomain爲true,這容許你將服務器端重定向到另外一個域。 |
|||||||||||||
scriptCharset |
只有當請求時dataType爲"jsonp"或"script",而且type是"GET"纔會用於修改charset。 由於此時是動態建立<script>來完成腳本加載,可是若是js中的編碼與頁面的編碼不一致時,js可能加載失敗或者顯示亂碼或者IE下報某符號錯誤。設置此參數就至關於爲<script>標籤設置charset屬性。 |
|||||||||||||
hearders |
(默認:{}) 設置HTTP請求頭數據"{鍵:值}"。此設置發生在:jQuery全部影響HTTP頭的參數(options)設置以後,beforeSend回調函數以前。 |
|||||||||||||
statusCode |
(默認:{}) 定義一組HTTP狀態碼與回調函數的映射,當響應的狀態碼有匹配statusCode則會觸發對應回調函數。例如,若是響應狀態是404,將觸發如下警報:
|
|||||||||||||
traditional |
若是你想要用傳統的方式來序列化數據,那麼就設置爲true。請參考$.param()深度遞歸詳解。 |
|||||||||||||
xhrFields |
聲明附加到XMLHttpRequest對象的自定義「key-value」數組。例如,若是須要的話,你能夠用它來設置跨域的withCredentials爲true,即: xhrFields: { withCredentials: true } |
|||||||||||||
5個局部事件 |
beforeSend、dataFilter、success、error、complete。(詳見後面事件介紹部分) |
|||||||||||||
由ajax函數內部解析或內部提供 |
||||||||||||||
dataTypes |
由dataType按空格拆分所得。 |
|||||||||||||
isLocal |
根據協議肯定當前url請求的是否爲本地請求。 jQuery中定義默認值爲:
|
|||||||||||||
hasContent |
非GET或HEAD請求爲true,用於處理data和contentType參數。 |
|||||||||||||
contents |
一個"{類型字符串:正則表達式}"的對象,假若dataTypes[0]爲「*」時,用contents中的正則表達式去匹配contentType,匹配成功則用「類型字符串」覆蓋dataTypes[0]。 jQuery內部定義以下:
|
|||||||||||||
accepts |
瀏覽器可以處理的媒體類型,其值取決於dataTypes[0]參數。 jQuery內部定義以下:
|
|||||||||||||
responseFields |
jqXHR超集設置「數據類型:屬性」對應關係,在返回響應數據時,用於肯定建立哪一個屬性變量。 jQuery中定義以下:
|
|||||||||||||
converters |
存儲數據類型對應的轉換器,根據dataTypes獲取對應轉換器,用於對響應數據response進行處理。該處理髮生在dataFilter回調函數以後。
|
|||||||||||||
2) jqXHR對象
爲不一樣瀏覽器內置的XMLHttpRequest提供了一致的超集。對於XMLHttpRequest以外的傳輸機制,好比JSONP請求,jXHR對象也能夠進行處理。
超集與真子集:
若是一個集合S2中的每個元素都在集合S1中,且集合S1中可能包含S2中沒有的元素,則集合S1就是S2的一個超集。 S1是S2的超集,則S2是S1的真子集,反之亦然。
jqXHR對象咱們經常使用以下成員,這些成員主要用於ajax的全局事件和局部事件,而且作爲$.ajax()函數返回值返回。
1
2
3
4
5
6
7
8
9
10
|
jqXHR:{
readyState
,setRequestHeader:
function
( name, value )
,getAllResponseHeaders:
function
()
,getResponseHeader:
function
( key )
,overrideMimeType:
function
( type )
,abort:
function
( statusText )
,responseText
,responseXML
}
|
另外,jqXHR的所有成員以下:
在圖中咱們看到一些陌生的函數,好比:done()、fail()、promise()、isResolve()、isRejected()、then()、always()、progress()等,都是jQuery的deferred對象API。
開發網站的過程當中,咱們常常遇到某些耗時很長的javascript操做。其中,既有異步的操做(好比ajax讀取服務器數據),也有同步的操做(好比遍歷一個大型數組),它們都不是當即能獲得結果的。
一般的作法是,爲它們指定回調函數(callback)。即事先規定,一旦它們運行結束,應該調用哪些函數。可是,在回調函數方面,jQuery的功能很是弱。爲了改變這一點,jQuery開發團隊就設計了deferred對象。
簡單說,deferred對象就是jQuery的回調函數解決方案。在英語中,defer的意思是"延遲",因此deferred對象的含義就是"延遲"到將來某個點再執行。 它解決了如何處理耗時操做的問題,對那些操做提供了更好的控制,以及統一的編程接口。
更專業的資源:jQuery的deferred對象詳解
jQuery框架中,伴隨Ajax請求會觸發若干事件,咱們能夠訂閱這些事件並在其中處理咱們的邏輯。在jQuery中有兩種Ajax事件:局部事件和全局事件。
1) 局部事件(回調函數),在$.ajax()方法的options參數中聲明,能夠用來設置請求數據和獲取、處理響應數據。
beforeSend |
該函數可在發送請求前修改XMLHttpRequest對象,如添加自定義 HTTP 頭。 簽名:function (jqXHR,s) { } 函數說明:傳入jqXHR、s對象 |
dataFilter |
在請求成功以後調用。若狀態碼爲304(未修改)則不觸發此回調。 簽名:function (data, dataType) { return newData; } 函數說明:傳入返回的數據、"dataType"參數的值。而且必須返回新的數據傳遞給success回調函數 |
success |
請求成功時觸發。 簽名:function (data,statusText,jqXHR) { } 函數說明:傳入返回的數據、描述狀態的字符串」success」、jqXHR對象 |
error |
請求失敗時調用此函數。 簽名:function (jqXHR, textStatus, errorThrown) { } 函數說明:傳入jqXHR對象、描述狀態的字符串」error」、錯誤信息 |
complete |
請求完成後回調函數 (請求成功或失敗以後均調用) 簽名:function (jqXHR, textStatus) { } 函數說明:傳入jqXHR對象、描述狀態的字符串(可能值:"No Transport"、"timeout"、"notmodified"---304 "、"parsererror"、"success"、"error") |
定義方式例如:
1
2
3
4
5
6
7
8
9
10
|
$.ajax({
// ...
beforeSend:
function
(){
// Handle the beforeSend event
},
complete:
function
(){
// Handle the complete event
}
// ...
});
|
2) 全局事件,每次Ajax請求都會觸發,它會向DOM中的全部元素廣播,你只需爲DOM中任意元素bind好全局事件即會觸發(若綁定屢次,則會依次觸發爲事件註冊的回調函數)。
ajaxStart |
開始新的Ajax請求,而且此時jQuery對象上沒有其餘ajax請求正在進行。 簽名:function(e) 函數說明:傳入事件對象 |
ajaxSend |
當一個Ajax請求開始時觸發 簽名:function(e,jqXHR,s) 函數說明:傳入事件對象、jqXHR、s對象 |
ajaxSuccess |
全局的請求成功 簽名:function(e,jqXHR,s,data) 函數說明:傳入事件對象、jqXHR、s對象、請求成功返回的相應數據 |
ajaxError |
全局的發生錯誤時觸發 簽名:function(e,jqXHR,s,errorData) 函數說明:傳入事件對象、jqXHR、s對象、請求失敗返回的錯誤信息 |
ajaxComplete |
全局的請求完成時觸發 簽名:function(e,jqXHR,s) 函數說明:傳入事件對象、jqXHR、s對象 |
ajaxStop |
當jQuery對象上正在進行Ajax請求都結束時觸發。 簽名:function(e) 函數說明:傳入事件對象 |
全局事件在jQuery中的聲明方式:
1
2
3
4
5
|
jQuery.each(
"ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend"
.split(
" "
),
function
( i, o ){
jQuery.fn[ o ] =
function
( f ){
return
this
.on( o, f );
};
});
|
因此咱們可使用下面兩種方式定義全局事件:
1
2
3
4
|
// 能夠用bind來綁定,用unbind來取消綁定。
$(
"#loading"
).bind(
"ajaxSend"
,
function
(){ … });
或者:
$(
"#loading"
).ajaxStart(
function
(){ … });
|
3) ajax方法完整的事件流
4) 示例:$.ajax()觸發的事件(局部事件和全局事件)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
// 全局事件
$(
"#div_event"
).ajaxStart(
function
(e) {
doAddEvent4textarea(
'txt_event'
,
'觸發ajaxStart回調函數'
);
});
$(
"#div_event"
).ajaxSend(
function
(e) {
doAddEvent4textarea(
'txt_event'
,
'觸發ajaxSend回調函數'
);
});
$(
"#div_event"
).ajaxSuccess(
function
(e, jqXHR, s, data) {
doAddEvent4textarea(
'txt_event'
,
'觸發ajaxSuccess回調函數'
);
});
$(
"#div_event"
).ajaxError(
function
(e, jqXHR, s, errorData) {
doAddEvent4textarea(
'txt_event'
,
'觸發ajaxError回調函數'
);
});
$(
"#div_event"
).ajaxComplete(
function
(e, jqXHR, s) {
doAddEvent4textarea(
'txt_event'
,
'觸發ajaxComplete回調函數'
);
});
$(
"#div_event"
).ajaxStop(
function
(e) {
doAddEvent4textarea(
'txt_event'
,
'觸發ajaxStop回調函數'
);
});
// 局部事件
function
bindLocalEvent(e) {
var
textareaid = e.data.textareaid;
var
global = e.data.global;
$.ajax(
'AjaxHandler.ashx?func=btn_nowTime_long'
,
{
type:
'get'
,
dataType:
'text'
,
global: global,
cache:
false
,
beforeSend:
function
(jqXHR, s) {
doAddEvent4textarea(textareaid,
'觸發beforeSend回調函數'
);
},
dataFilter:
function
(data, dataType) {
doAddEvent4textarea(textareaid,
'觸發dataFilter回調函數'
);
},
success:
function
(data, statusText, jqXHR) {
doAddEvent4textarea(textareaid,
'觸發success回調函數'
);
},
error:
function
(jqXHR, textStatus, errorThrown) {
doAddEvent4textarea(textareaid,
'觸發error回調函數'
);
},
complete:
function
(jqXHR, textStatus) {
doAddEvent4textarea(textareaid,
'觸發complete回調函數'
);
}
});
}
function
doAddEvent4textarea(textareaid, txt) {
var
textarea = $(
"#"
+ textareaid);
textarea.val(textarea.val() +
'\r\n'
+ txt);
}
|
效果圖:
5) $.ajax()方法的全局事件典型用例
你的頁面存在多個甚至爲數很多的ajax請求,可是這些ajax請求都有相同的消息機制。ajax請求開始前顯示一個提示框,提示「正在讀取數據」;ajax請求成功時提示框顯示「數據獲取成功」;ajax請求結束後隱藏提示框。
a) 不使用全局事件的作法是:
給$.ajax()加上beforeSend、success、complete回調函數,在回調函數中加上處理提示框。
b) 使用全局事件的作法是:
1
2
3
4
5
6
|
$(document).ajaxStart(onStart)
.ajaxComplete(onComplete)
.ajaxSuccess(onSuccess);
function
onStart(event) {
//..... }
function
onComplete(event, xhr, settings) {
//..... }
function
onSuccess(event, xhr, settings) {
//..... }
|
1) jQuery.ajaxSetup({ })
jQuery.ajax()函數中的全部的參數選項均可以經過jQuery.ajaxSetup()函數來全局設置默認值。
2) $.ajax()函數的封裝
a) $("").load(url [, params] [, callback])
請求遠程的HTML文件代碼(dataType: "html"),默認使用 GET 方式,若是傳遞了params參數則使用Post方式。在請求「成功」完成時將responseText屬性值插入至DOM中。但無論請求是否成功完成「在最後」都會執行callback回調函數(即:complete:callback)。
b) jQuery.get(url [, data] [, callback] [, type] )
經過HTTP GET請求載入數據,並在請求成功時執行回調函數(即:success: callback)。
c) jQuery.getJSON(url [, data] [, callback] )
經過 HTTP GET 請求載入 JSON 數據。至關於: jQuery.get(url, [data],[callback], "json")
能夠經過使用JSONP 形式的回調函數來加載其餘網域的JSON數據。
d) jQuery.getScript(url [, callback] )
經過 HTTP GET 請求載入並執行一個 JavaScript 文件。至關於: jQuery.get(url, null, [callback], "script")
能夠跨域調用 JavaScript 文件。
e) jQuery.post(url [, data] [, callback] [, type] )
經過 HTTP POST 請求載入信息,並在請求成功時執行回調函數(即:success: callback)。
3) 對象序列化
a) jQuery.param(object,traditional)
建立數組或對象的序列化表示,該序列化可在ajax請求時在URL查詢字符串中使用。
序列化過程當中會使用encodeURIComponent()函數把字符串做爲URI組件進行編碼。
encodeURIComponent() 方法不會對 ASCII 字母和數字進行編碼,也不會對這些 ASCII 標點符號進行編碼: - _ . ! ~ * ' ( ) 。其餘字符(好比:;/?:@&=+$,# 這些用於分隔 URI 組件的標點符號),都是由一個或多個十六進制的轉義序列替換的。
1
2
3
4
5
6
|
// 在param中會進行以下處理
function
( key, value ) {
// 若是value是函數,則取其函數返回值
value = jQuery.isFunction( value ) ? value() : value;
s[ s.length ] = encodeURIComponent( key ) +
"="
+ encodeURIComponent( value );
};
|
對於 jQuery 1.4,$.param() 方法將會經過深度遞歸的方式序列化對象,以便符合現代化腳本語言的需求,好比 PHP、Ruby on Rails 等。你能夠傳遞traditional = true 或在ajax功能中傳遞包含traditional的options參數。
傳送門:$.param()深度遞歸詳解和$.param() 示例
b) $("").serializeArray()
能夠將一個或多個表單元素(好比 input、 textarea等),或者 form 元素自己的jQuery對象序列化爲JSON對象。(非 JSON 字符串。須要使用插件或者第三方庫進行字符串化操做)
特別說明,元素不能被禁用(禁用的元素不會被包括在內),而且元素應當有含有 name 屬性。提交按鈕的值也不會被序列化。文件選擇元素的數據也不會被序列化。
c) $("").serialize()
能夠將一個或多個表單元素(好比 input、 textarea等),或者 form 元素自己的jQuery對象序列化爲通過URL編碼轉換後的字符串,可直接用在URL查詢字符串中。
jQuery內部定義:
1
2
3
|
serialize:
function
() {
return
jQuery.param(
this
.serializeArray() );
}
|
$.ajax()中常見應用示例
1) cache參數:GET和POST最重要的區別(傳送門)
語義上,GET是獲取指定URL上的資源,是讀操做,重要的一點是不論對某個資源GET多少次,它的狀態是不會改變的,在這個意義上,咱們說GET是安全的(不是被密碼學或者數據保護意義上的安全)。由於GET是安全的,因此GET返回的內容能夠被瀏覽器,Cache服務器緩存起來。
而POST的語意是對指定資源「追加/添加」數據,因此是不安全的,每次提交的POST,參與的代碼都會認爲這個操做會修改操做對象資源的狀態,因而,瀏覽器在你按下F5的時候會跳出確認框,緩存服務器不會緩存POST請求返回內容。
2) ifModified參數:經過ifModified參數提升請求性能(即:「條件GET」:Last-Modified / If-Modified-Since和ETag / If-None-Match)
當你請求的資源並非一層不變的時候,即不能簡單的一直使用客戶端緩存時,你可能經過將cache設置爲false來發送請求,這其實是在url加上時間戳組合成新的url,每次發送新的請求,這明顯加大了服務器的壓力。
對於這種狀況,咱們能夠經過ifModified參數改進緩存方式(即:cache和ifModified都設置爲true),僅在請求的數據改變時從新獲取。經過這種方式請求的url不會改變,而且每次都會發送到服務器,只是會有檢驗方法驗證是否須要從新獲取數據從而節省帶寬和開銷。
更多ETag描述(優勢,解決了Last-Modified沒法解決的一些問題,什麼場合不該該被使用)
過程以下:
a) 將$.ajax()函數的cache和ifModified參數同時設置爲true。
b) 客戶端請求服務端A,在服務端加上Last-Modified/ETag響應體一塊兒返回。
c) 客戶端緩存接收到的Last-Modified/ETag響應體,並在下一次發生請求A時將緩存的Last-Modified/ETag值作爲If-Modified-Since/IF-None-Match請求頭一塊兒發給服務器。
d) 服務器接收If-Modified-Since/IF-None-Match後,就根據參數值檢驗自上次客服端請求以後資源是否有改動
e) 這樣,既保證不向客戶端重複發出資源,也保證當服務器有變化時,客戶端可以獲得最新的資源。
這一過程當中,咱們只須要作:服務器返回Last-Modified/ETag響應頭和在服務端檢驗數據是否失效並採起對應處理方式。其他步驟由jQuery框架的ajax()函數完成。
關鍵代碼以下:
客服端:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
$(
'#btn_nowTime_long3'
).bind(
'click'
,
null
,
function
() {
$.ajax(
'AjaxHandler.ashx?func=GetServerTime4Modified'
,
{
type:
'get'
,
dataType:
'text'
,
cache:
true
,
ifModified:
true
,
success:
function
(data) {
if
(data)
alert(data);
},
});
});
|
服務端:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
if
(!String.IsNullOrEmpty(context.Request.Headers[
"If-Modified-Since"
]))
{
if
(CheckResourceValidate())
// 檢查資源有效性
{
// 若是資源有效,則直接返回304狀態碼,客戶端回去到此狀態碼後會從緩存中取值。
context.Response.StatusCode = 304;
return
;
}
}
// 請求數據
GetServerTimeAfter2Second();
context.Response.Cache.SetExpires(DateTime.Now.AddSeconds(5));
// 設置Last-Modified響應體
context.Response.Cache.SetLastModified(DateTime.Now);
|
在JavaScript中,有一個很重要的安全性限制,被稱爲「Same-Origin Policy」(同源策略)。這一策略對於JavaScript代碼可以訪問的頁面內容作了很重要的限制,即JavaScript只能訪問與包含它的文檔在同一域下的內容。所謂同源是指,域名(host),協議(protocol),端口(port)相同。
URL |
說明 |
是否容許通訊 |
可否經過javascript解決 |
http://www.a.com/a.js http://www.a.com/b.js |
同一域名下 |
容許 |
|
http://www.a.com/lab/a.js http://www.a.com/script/b.js |
同一域名下不一樣文件夾 |
容許 |
|
http://www.a.com:8000/a.js http://www.a.com/b.js |
同一域名,不一樣端口 |
不容許 |
能 |
http://www.a.com/a.js https://www.a.com/b.js |
同一域名,不一樣協議(http和https) |
不容許 |
不能 |
http://www.a.com/a.js http://70.32.92.74/b.js |
不容許 |
能 |
|
http://www.cnblogs.com/a.js http://www.a.com/b.js http://script.a.com/b.js http://a.com/b.js |
不一樣域名(host) |
不容許 |
能 |
1) $.ajax()爲咱們提供了兩種解決方案,不過都是隻支持get方式,分別是jQuery的jQuery.ajax「jsonp」格式和jquery.getScript()(即jQuery.ajax 「script」格式)方式。
2) $.ajax()跨域原理分析
因爲javascript的安全限制「同源策略」,因此咱們沒法使用XMLHttpRequest直接請求別的域名下的資源。不過擁有src屬性和href屬性的<script>\<img>\<iframe>和<link>\<a>標籤不受同源策略影響。$.ajax()提供的兩種解決方案正是應用了動態建立<script>的方式來實現(即:生成<script>標籤,src引入腳本,而後執行,最後移除<script>標籤)。
3) jQuery.ajax()的jsonp和script方式的異同點:
a) 相同:都走$.ajax() script格式的流程;不會觸發全局事件和局部事件;只支持GET方式(POST請求會自動轉化爲GET請求);默認不啓用緩存(cache:false)
b) 不一樣:jsonp方式能夠經過jsonp和jsonpCallback參數指定一個特定回調函數。
4) 示例部署說明:
由於是跨域請求,因此須要在本機部署兩個示例程序以模擬不一樣域之間的訪問,而且在示例代碼中須要修改「crossUrl」爲目的域路徑。
5) jsonp示例代碼:
客服端:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
// jsonp方式跨域請求(dataType:jsonp)
$(
'#btn_cross_req1'
).bind(
'click'
,
null
,
function
() {
$.ajax(crossUrl,
{
type:
'get'
,
dataType:
'jsonp'
,
jsonp:
'jsonpParamName'
,
jsonpCallback:
'crossCallback'
,
crossDomain:
true
,
});
});
function
crossCallback(data) {
alert(
'jsonp'
+ data);
}
|
服務端:
1
2
3
4
|
context.Response.ContentType =
"text/plain"
;
string
jsonpCallbackName = reqCollection[
"jsonpParamName"
];
context.Response.Write(String.Format(
"{0}('來自域:{1}的相應信息')"
, jsonpCallbackName, context.Request.Url.Host));
|
分析:
a) 因jsonp和jsonpCallback參數而改變的url以下。(即默認爲:callback=jQuery隨機值,更改成:jsonpParamName=crossCallback)
URL:http://192.168.1.100:6567/AjaxHandler.ashx?func=CrossRequest&jsonpParamName=crossCallback&_=1368360234428
b) 服務器端獲取到jsonp回調函數名後,返回一個函數表達式。
6) 在XMLHttpRequest Level 2中新增了跨域訪問方式、接收二進制等新功能,詳細請看:XMLHttpRequest2 新技巧