寫在前面:javascript
先講講ajax中的相關函數,而後結合函數功能來具體分析源代碼。java
相關函數:jquery
>>ajax全局事件處理程序ajax
.ajaxStart(handler) | 註冊一個ajaxStart事件處理器。當一個Ajax請求開始,而且同時無其它未完成的Ajax請求時,jQuery觸發ajaxStart事件。 |
.ajaxSend(handler) | 註冊一個ajaxSend事件處理器。當一個Ajax請求被髮送時觸發ajaxSend事件。 |
.ajaxSuccess(handler) | 註冊一個ajaxSuccess事件處理器。當一個Ajax請求成功時觸發ajaxSuccess事件。 |
.ajaxError(handler) | 註冊一個ajaxError事件處理器。當一個Ajax請求出錯時觸發ajaxError事件。 |
.ajaxComplete(handler) | 註冊一個ajaxComplete事件處理器。當一個Ajax請求完成時觸發ajaxComplete事件。 |
.ajaxStop(handler) | 註冊一個ajaxStop事件處理器。,當一個Ajax請求完成,而且同時無其它未完成的Ajax請求時觸發ajaxStop事件。 |
注意:json
這六個Ajax全局事件的處理函數都應該註冊在document上。api
例如: $(document).ajaxSuccess(handler);跨域
ajax選項中的global是全局ajax事件的開關。若是global選項設置爲false,上面的全部ajax全局事件都不會被觸發。瀏覽器
特別注意的是ajaxStart和ajaxStop事件上面描述的文字的不一樣之處。緩存
>> Ajax的基本函數架構
jQuery.ajaxSetup(options) 設置Ajax默認的選項。
options對象包含用來配置ajax請求的key/value鍵值對。
函數直接擴展了jQuery.ajaxSetting這個對象,這個對象是Ajax請求的默認的配置對象,擴展後對之後的每一個Ajax請求都將產生影響。所以非特殊狀況不推薦擴展Ajax的默認選項。
Ajax源碼中的使用
//擴展jQuery.ajaxSetting默認選項集合 jQuery.ajaxSetup({ accepts: { script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript" }, contents: { script: /(?:java|ecma)script/ }, converters: { "text script": function( text ) { jQuery.globalEval( text ); return text; } } });上面的代碼,擴展了jQuery.ajaxSetting中的三個默認屬性,accepts、contents、converters,這三個屬性對象添加對script數據類型的支持。後面介紹這三個選項的用途。
jQuery.ajaxPrefilter( )
jQuery.ajaxPrefilter([dataTypes,]handler)
在每一個ajax請求開始以前,對請求作前置處理。
dataTypes是包含一個或者多個空格分開的dataType的字符串。 用來限定前置處理應用的Ajax請求的範圍。 dataTypes參數可選,默認是」*」,當某個dataType的前置處理函數隊列執行完畢後,最終會執行」*」對應的處理函數隊列。
handler參數 function(options,originalOptions,jqXHR) 即具體的處理函數,其中options參數表明用戶選項集合即originalOptions和默認選項集合即jQuery.ajaxSetting綜合後的請求最終使用選項集合,originalOptions表明調用ajax函數時的用戶選項集合,jqXHR是jQuery封裝的XHR對象,包含相關的屬性和方法。
栗子: 在jQuery源碼中,Ajax模塊有兩處使用了這個函數。
// Handle cache's special case and global //script類型請求的前置處理 //a.默認不使用瀏覽器緩存 //b.對於跨域請求:使用get方法,而且設置global爲false,即不觸發全局ajax對象。 jQuery.ajaxPrefilter( "script", function( s ) { if ( s.cache === undefined ) { s.cache = false; } if ( s.crossDomain ) { s.type = "GET"; s.global = false; } }); // Detect, normalize options and install callbacks for jsonp requests //對json和jsonp類型ajax請求的前置處理 jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) { //省略其它內容...return "script";}注意:
針對某個數據類型dataType,你能夠註冊多個處理函數。函數會依次執行。
處理函數能夠返回一個dataType字符串,此時jQuery不會繼續執行隊列中的其它後續處理函數,而是將此字符串添加到請求選項的dataTypes頭部,而且轉而執行此字符串所對應的前置處理程序。
例如上面的代碼中,在對json和jsonp的前置處理中,返回」script」,那麼script字符串會被添加到options.dataTypes頭部(options就是前面提到的請求最終使用的選項集合),而且會跳轉到執行」script」對應的前置處理程序。
jQuery.ajaxTransport( )
jQuery.ajaxTransport(dataType,handler)
dataType 表示請求的數據類型。
handler函數,function(options,originalOption,jqXHR) ,函數返回一個對象,這個表明請求此數據類型時,實際使用的完成傳輸行爲的對象。我把它稱做傳輸對象。傳輸對象應該包含兩個方法,send和abort。 jQuery內部會爲每一個對應此數據類型的Ajax請求建立這個傳輸對象。
調用過程就像下面這樣:
$.ajaxTransport( dataType, function( options, originalOptions, jqXHR ) { if( /* transportCanHandleRequest */ ) { return { send: function( headers, completeCallback ) { // Send code }, abort: function() { // Abort code } }; } });其中,send函數的參數
headers
對象 包含請求頭的各類設置completeCallback 函數 當傳輸過程完成時,調用此函數來告訴Ajax傳輸過程結束。
completeCallback接受四個參數 ( status, statusText, responses, headers )
其中responses是包含 dataType/value 的對象。例如像這樣的{ xml: XMLData, text: textData }
這個函數爲ajax請求帶來了極大的靈活性,你能夠定製本身的傳輸過程。例如,你能夠定製一個dataType爲」image」的ajax請求
$.ajaxTransport( "image", function( s ) { if ( s.type === "GET" && s.async ) { var image; return { send: function( _ , callback ) { image = new Image(); function done( status ) { if ( image ) { var statusText = ( status === 200 ) ? "success" : "error", tmp = image; image = image.onreadystatechange = image.onerror = image.onload = null; callback( status, statusText, { image: tmp } ); } } image.onreadystatechange = image.onload = function() { done( 200 ); }; image.onerror = function() { done( 404 ); }; image.src = s.url; }, abort: function() { if ( image ) { image = image.onreadystatechange = image.onerror = image.onload = null; } } }; } });注意到上面callback( status, statusText, { image: tmp } ); callback函數的response參數值是{image:tmp}, image對應數據類型。
jQuery的Ajax模塊源代碼中,有兩處調用了ajaxTransport函數。
一種用來生成是Ajax默認的傳輸對象。
jQuery.ajaxTransport(function( s ) {
//建立"*"對應的transport,即默認處理全部請求的transport//代碼省略
});
上面的ajaxTransport調用省略了dataType參數,此時建立的就是」*」對應的傳輸過程,即默認使用的傳輸過程。
另一種狀況,ajax對於跨域的」script」數據類型的請求,使用特殊的傳輸對象。
// Bind script tag hack transport //請求script文件使用的傳輸對象。 jQuery.ajaxTransport( "script", function(s) { // This transport only deals with cross domain requests //只處理跨域的script數據類型//能夠看到跨域的script文件是經過HTML的script標籤請求並執行。 if ( s.crossDomain ) { var script, head = document.head || jQuery("head")[0] || document.documentElement; return { send: function( _, callback ) { script = document.createElement("script"); script.async = true; if ( s.scriptCharset ) { script.charset = s.scriptCharset; } script.src = s.url; // Attach handlers for all browsers //isAbort參數在下面定義的abort方法中手動調用script.onload函數時設爲true //IE的 script 元素支持onreadystatechange事件,不支持onload事件。 //FF的script 元素不支持onreadystatechange事件,只支持onload事件。 script.onload = script.onreadystatechange = function( _, isAbort ) { //isAbort時,作清除script的處理 //!script.readyState 說明是在FF下面,此時代表load完成 ///loaded|complete/.test( script.readyState )代表在IE下須要檢測到readyState爲loaded或者complete時,纔算load完成 if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) { // Handle memory leak in IE script.onload = script.onreadystatechange = null; // Remove the script if ( script.parentNode ) { script.parentNode.removeChild( script ); } // Dereference the script script = null; // Callback if not abort if ( !isAbort ) { callback( 200, "success" ); } } }; // Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending // Use native DOM manipulation to avoid our domManip AJAX trickery head.insertBefore( script, head.firstChild ); }, abort: function() { if ( script ) { script.onload( undefined, true ); } } }; } });注意:
與前面講的ajaxPrefilter類似,每種數據類型能夠定義多個傳輸函數。若是其中一個函數返回了傳輸對象,那麼就終止函數隊列的調用。若是具體數據類型未獲得傳輸對象,最後會調用「*」對應的傳輸函數隊列。
jQuery.ajax()
放在單獨的一個篇文章裏
>> ajax相關的快捷方法
jQuery.post()
jQuery.get()
jQuery.getJSON()
jQuery.getScript()
.load()
另起一片文章講。
>> Ajax源代碼的架構和流程分析
另起一片文章講。
>>ajax返回jqXHR對象分析,關於Deferred對象
另起一片文章講。
最後: 第一次寫,寫文章果真麻煩,感受內容量好大,一時半會兒寫不完,仍是分多個板塊來寫吧。先直接貼Ajax模塊的源代碼(帶註解)。