jQuery源碼分析系列(33) : AJAX中的前置過濾器和請求分發器

來源:互聯網
上載者:User

標籤:c   style   class   blog   code   java   

jQuery1.5以後,AJAX模組提供了三個新的方法用於管理、擴充AJAX請求,分別是:

1.前置過濾器 jQuery. ajaxPrefilter

2.請求分發器 jQuery. ajaxTransport,

3.類型轉換器 ajaxConvert

源碼結構:

jQuery.extend({    /**     * 前置過濾器     * @type {[type]}     */    ajaxPrefilter: addToPrefiltersOrTransports(prefilters),    /**     * 請求分發器     * @type {[type]}     */    ajaxTransport: addToPrefiltersOrTransports(transports),         ...........................});

可見這2個方法是通過私人方法addToPrefiltersOrTransports通過curry手段構造的,分別是保持了prefilters與transports的引用

 

來個簡單的類比這個結構

var prefilters = 2;var addToPrefiltersOrTransports = function(prefilters) {    return function(b) {        return prefilters + b;    }}var ajaxPrefilter = addToPrefiltersOrTransports(prefilters)ajaxPrefilter(1) //3

可見ajaxPrefilter就維持了addToPrefiltersOrTransports返回函數的引用了,這種就是閉包的手法了,這也是JS的開發人員都需要掌握的

好處就是合并多個參數,當然因為維持引用代價就是一點點效能消耗

 

當然jQuery不是傳遞的簡單類型處理,還可以傳遞的一個參考型別的回呼函數,所以針對ajaxPrefilter方法放閉包構件就需要做一些處理了

填充prefilters處理器

var prefilters = {};var addToPrefiltersOrTransports = function(structure) {    return function(func) {        structure[‘*‘] = func;    }}var ajaxPrefilter = addToPrefiltersOrTransports(prefilters)ajaxPrefilter(function(options){    return {        send:function(){        },        callback:function(){        }    }})

其實說白了就是把對應的方法製作能函數的形式填充到prefilters或者transports對應的處理封裝對象中

要用的時候直接執行,每個函數都保持著各自的引用

這種寫法的好處自然是靈活,易維護,減少代碼量

還有我們經常的使用的,jQuery的代碼很簡練,比如合并多個方法的建立等等

jQuery.each([        "tabIndex",        "readOnly",        "maxLength",        "contentEditable"    ], function() {        jQuery.propFix[this.toLowerCase()] = this;    });

 

所以此時的prefilters中的結構就是

prefilters = {        ‘*‘: function() {            return {                send: function() {                },                callback: function() {                }            }        }    }

 

迴歸重點,那麼引入ajaxPrefilter與ajaxTransport的作用是幹嘛?

前置過濾器和請求分發器在執行時,分別遍曆內部變數prefilters和transports,這兩個變數在jQuery載入完畢後立即初始化,從過閉包的方法填充這個2個對象

 

ajaxPrefilter與ajaxTransport都是通過inspectPrefiltersOrTransports構建器

prefilters中的前置過濾器在請求發送之前、佈建要求參數的過程中被調用,調用prefilters的是函數inspectPrefiltersOrTransports;

巧妙的是,transports中的請求分發器在大部分參數設定完成後,也通過函數inspectPrefiltersOrTransports取到與請求類型匹配的請求分發器:

function inspectPrefiltersOrTransports(structure, options, originalOptions, jqXHR) {    var inspected = {},        seekingTransport = (structure === transports);    function inspect(dataType) {        var selected;        inspected[dataType] = true;        jQuery.each(structure[dataType] || [], function(_, prefilterOrFactory) {            var dataTypeOrTransport = prefilterOrFactory(options, originalOptions, jqXHR);            if (typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[dataTypeOrTransport]) {                options.dataTypes.unshift(dataTypeOrTransport);                inspect(dataTypeOrTransport);                return false;            } else if (seekingTransport) {                return !(selected = dataTypeOrTransport);            }        });        return selected;    }    return inspect(options.dataTypes[0]) || !inspected["*"] && inspect("*");}

遍曆structure[dataType]數組,並執行回調
prefilterOrFactory為函數數組元素
執行該函數如果返回的結果dataTypeOrTransport是字串且時prefilters且沒有被inspected過
就給options.dataTypes數組頭部添加該字串
繼續遞迴dataTypeOrTransport(當我們使用json/jsonp的時候會返回“script”,於是會執行“script”相關的回調)
如果是transport就返回dataTypeOrTransport的假結果

 

前置過濾器 prefilters

簡單的說就是一種hack的做法,只是說比起事件的那種hack寫的手法實現更為高明

我們可以看看針對prefilters的方法其實就是dataType為 script,json,jsonp的處理

當我們動態載入指令檔比如

$.ajax({    type     : "GET",    url      : "test.js",    dataType : "script"});

所以在inspectPrefiltersOrTransports方法中prefilters[script]能找到對應的處理方法,所以就會執行

例如script的hack,要強制加上處理緩衝的特殊情況和crossDomain

因為設定script的前置過濾器,script並不一定意思著跨域

跨域未被禁用,強制類型為GET,不觸發全域時間

jQuery.ajaxPrefilter("script", function(s) {    if (s.cache === undefined) {        s.cache = false;    }    if (s.crossDomain) {        s.type = "GET";    }});

所以prefilters就是在特定的環境針對特定的情況做一些必要的相容的處理

 

請求分發器 transports

請求分發器顧名思義發送請求,那麼底層的ajax發送請求是通過send方法

xhr.send();

但是jQuery對send方法做了拆分,把對應的處理放到了transports中了

那麼transports對象也是類似前置處理器通過jQuery.ajaxTransport構建

例如script,send,abort方法

返回出transports方法

transport = inspectPrefiltersOrTransports(transports, s, options, jqXHR);

如果您覺得這文章對您有協助,請點擊【推薦一下】,想跟我一起進步嗎?那就【關注】我吧!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.