jQuery源码 Ajax模块分析
寫在前面:
先講講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事件。 |
注意:
這六個Ajax全局事件的處理函數都應該注冊在document上。
?? 例如: $(document).ajaxSuccess(handler);
ajax選項中的global是全局ajax事件的開關。如果global選項設置為false,上面的所有ajax全局事件都不會被觸發。
特別注意的是ajaxStart和ajaxStop事件上面描述的文字的不同之處。
>> Ajax的基本函數
jQuery.ajaxSetup()
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 IEscript.onload = script.onreadystatechange = null;// Remove the scriptif ( script.parentNode ) {script.parentNode.removeChild( script );}// Dereference the scriptscript = null;// Callback if not abortif ( !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模塊的源代碼(帶注解)。
轉載于:https://www.cnblogs.com/cheerfulCoder/p/4047456.html
總結
以上是生活随笔為你收集整理的jQuery源码 Ajax模块分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 部分 CM11 系统 Android 平
- 下一篇: 关于Task类处理多线程简单示例