ajax詳解

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 頭部詳解

Accept

瀏覽器可以處理的媒體類型

Accept-Charset

瀏覽器申明本身接收的字符集

Accept-Encoding

瀏覽器申明本身接收的編碼方法,一般指定壓縮方法,是否支持壓縮,支持什麼壓縮方法(gzip,deflate)

Host

客戶端指定要請求的WEB服務器的域名/IP 地址和端口號

Referer

發出請求的頁面的URI

Content-Type

標明發送或者接收的實體的MIME類型。傳送門:

1HTTP Content-type對照表

2格式:Content-Type: [type]/[subtype]; parameter

X-Requested-With

非標準HTTP頭,只爲firefox3標註是否爲ajax異步請求,null表示爲同步請求。

默認狀況下,服務器對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 發生變化:

0(未初始化)

對象已創建,可是還沒有初始化(還沒有調用open方法)

1(初始化)

對象已創建,還沒有調用send方法

2(發送數據)

send方法已調用,可是當前的狀態及http頭未知

3(數據傳送中)

已接收部分數據,由於響應及http頭不全,這時經過responseBody和responseText獲取部分數據會出現錯誤

4(完成)

數據接收完畢,此時能夠經過responseXml和responseText獲取完整的迴應數據

 

status(數字表示)

返回當前請求的http狀態碼。

傳送門:HTTP狀態碼一覽表(HTTP Status Code

1xx(臨時響應)

表示臨時響應並須要請求者繼續執行操做的狀態代碼。

2xx (成功)

表示成功處理了請求的狀態代碼。Eg:200

3xx (重定向)

表示要完成請求,須要進一步操做。一般,這些狀態代碼用來重定向。Eg:304

4xx(請求錯誤)

這些狀態代碼表示請求可能出錯,致使服務器沒法正常處理。Eg:404

5xx(服務器錯誤)

這些狀態代碼表示服務器在嘗試處理請求時發生內部錯誤。這些錯誤多是服務器自己的錯誤,而不是請求出錯。Eg:500

 

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 草案。

  1. 老版本的缺點

老版本的XMLHttpRequest對象有如下幾個缺點:

1)   只支持文本數據的傳送,沒法用來讀取和上傳二進制文件。

2)   傳送和接收數據時,沒有進度信息,只能提示有沒有完成。

3)   受到"同域限制"(Same Origin Policy),只能向同一域名的服務器請求數據。

  1. 新版本的功能

新版本的XMLHttpRequest對象,針對老版本的缺點,作出了大幅改進。

1)   能夠設置 HTTP 請求的時限。

2)   可使用FormData對象管理表單數據。

3)   能夠上傳文件。

4)   能夠請求不一樣域名下的數據(跨域資源共享,Cross-origin resource sharing,簡稱 CORS)。

5)   能夠獲取服務器端的二進制數據。

6)   能夠得到數據傳輸的進度信息。

  1. 介紹幾個XMLHttpRequest Leve2 新增的成員

 

超時時限

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. 一個新功能實例

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
     }
}
  1. 更多XMLHttpRequest Level 2新功能描述請看:

1)   XMLHttpRequest 加強功能

2)   XMLHttpRequest Level 2 使用指南

3)   XMLHttpRequest2 新技巧

 

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。

 

  1. jQuery.ajax( [url,] options )

    經過 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 來得到一致的結果。

可用值:

"xml"

返回 XML 文檔,可用jQuery處理。

"html"

返回純文本 HTML 信息;包含的 script標籤會在插入dom時執行

"script"

返回純文本 JavaScript 代碼,經常用於跨域請求。不會觸發全局事件和局部事件;只支持GET方式(POST請求會自動轉化爲GET請求);默認不啓用緩存(cache:false)

"json"

返回 JSON 數據。JSON 數據是一種能很方便經過 JavaScript 解析的結構化數據。

"jsonp"

JSONP 格式,用於跨域請求。

"text"

返回純文本字符串

其中,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&amp;key2=value2 ,也能夠是一個映射,好比 {key1: 'value1', key2: 'value2'} 。若是使用了後者的形式,則數據在發送前會經過jQuery.param()函數轉換成查詢字符串。這個處理過程也能夠經過設置processData選項爲false來回避。

processData

(默認: true) 默認狀況下,發送到服務器的數據(即data參數)將被轉換爲字符串以配合默認內容類型"application/x-www-form-urlencoded"。若是要發送 DOM 樹信息或其它不但願轉換的信息,請設置爲false。

jQuery中的處理方式:

1
2
3
if  ( s.data&&s.processData&&typeofs.data !== "string"  ) {
     s.data = jQuery.param(s.data, s.traditional );
}

async

(默認: true) 默認設置下,全部請求均爲異步請求。若是須要發送同步請求,請將此選項設置爲 false。注意,同步請求將鎖住瀏覽器,用戶其它操做必須等待請求完成才能夠執行。

timeout

設置請求超時時間(毫秒)。經過setTimeout(fn,time)實現。

cache

(默認: true)dataType爲 script 和jsonp時默認爲 false。設置爲 false 將不緩存此頁面。

當使用GET或HEAD方式發送請求時要添加時間戳參數 (net Date()).getTime() 來保證每次發送的URL不一樣, 能夠避免瀏覽器緩存.(只有GET和HEAD方式的請求瀏覽器纔會緩存)

jQuery中的處理方式:

1
2
3
4
5
6
7
if  ( s.cache === false  ) {
     var  ts = jQuery.now(),
     // rts = /([?&])_=[^&]*/嘗試替換
     ret = s.url.replace( rts, "$1_="  + ts );
     // rquery = /\?/若是沒有替換任何內容,則把時間戳加到url最後
     s.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? "&"  : "?"  ) + "_="  + ts : ""  );
}

示例:/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,將觸發如下警報:

1
2
3
4
5
$.ajax({
     statusCode: {404: function () {
        alert( 'page not found' );
     }
});

traditional

若是你想要用傳統的方式來序列化數據,那麼就設置爲true。請參考$.param()深度遞歸詳解

xhrFields

聲明附加到XMLHttpRequest對象的自定義「key-value」數組。例如,若是須要的話,你能夠用它來設置跨域的withCredentials爲true,即:

xhrFields: { withCredentials: true }  

5個局部事件

beforeSend、dataFilter、success、error、complete。(詳見後面事件介紹部分)

 

由ajax函數內部解析或內部提供

dataTypes

由dataType按空格拆分所得。

isLocal

根據協議肯定當前url請求的是否爲本地請求。

jQuery中定義默認值爲:

1
isLocal:/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/.test(/^([\w\+\.\-]+:)(?:\/\/([^\/? #:]*)(?::(\d+))?)?/.exec(url))

hasContent

非GET或HEAD請求爲true,用於處理data和contentType參數。

contents

一個"{類型字符串:正則表達式}"的對象,假若dataTypes[0]爲「*」時,用contents中的正則表達式去匹配contentType,匹配成功則用「類型字符串」覆蓋dataTypes[0]。

jQuery內部定義以下:

1
2
3
4
5
6
contents: {
     xml: /xml/,
     html: /html/,
     json: /json/,
     script: /javascript|ecmascript/
}

accepts

瀏覽器可以處理的媒體類型,其值取決於dataTypes[0]參數。

jQuery內部定義以下:

1
2
3
4
5
6
7
8
accepts: {
     xml: "application/xml, text/xml" ,
     html: "text/html" ,
     text: "text/plain" ,
     json: "application/json, text/javascript" ,
     script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript" ,
     "*" : allTypes    // dataTypes[0]匹配不上時取此值
}

responseFields

jqXHR超集設置「數據類型:屬性」對應關係,在返回響應數據時,用於肯定建立哪一個屬性變量。

jQuery中定義以下:

1
2
3
4
responseFields: {
     xml: "responseXML" ,
     text: "responseText"
}

converters

存儲數據類型對應的轉換器,根據dataTypes獲取對應轉換器,用於對響應數據response進行處理。該處理髮生在dataFilter回調函數以後。

1
2
3
4
5
6
7
8
9
10
converters: {
     "* text" : window.String,
     "text html" : true ,
     "text json" : jQuery.parseJSON,
     "text xml" : jQuery.parseXML,
     "text script" : function ( text ) {
             jQuery.globalEval( text );  // 執行腳本
             return  text;
         }
}
     

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對象詳解

 

  1. jQuery Ajax事件

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 ajax相關函數

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 屬性。提交按鈕的值也不會被序列化。文件選擇元素的數據也不會被序列化。

           傳送門:$("").serializeArray() 示例

c)   $("").serialize()

能夠將一個或多個表單元素(好比 input、 textarea等),或者 form 元素自己的jQuery對象序列化爲通過URL編碼轉換後的字符串,可直接用在URL查詢字符串中。

       jQuery內部定義:

1
2
3
serialize: function () {
     return  jQuery.param( this .serializeArray() );
}

傳送門:$("").serialize()示例

 

$.ajax()中常見應用示例

  1. cache和ifModified參數

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後,就根據參數值檢驗自上次客服端請求以後資源是否有改動

  1.                           i.      若還未改動則直接返回響應304和一個空的響應體。
  2.                         ii.      若已改動則從新處理數據,返回最新的請求數據。

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);
  1. 跨域請求

在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

域名和域名對應ip

不容許

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 新技巧

 

原文地址:

相關文章
相關標籤/搜索