在異步機(jī)制這章我們詳細(xì)的分析了 deferred 的設(shè)計(jì),其中提供了 deferred.promise 方法就是把普通對象轉(zhuǎn)化成 deferred 對象了,ajax 就是把 deferred 對象給摻進(jìn)去可以讓整個 Ajax 方法變成了一個 deferred 對象,在Ajax方法中返回的是 jqXHR 一個包裝對象,在這個對象里面混入了所有實(shí)現(xiàn)方法。
ajax: function(url, options) { var jqXHR = {} //ajax對象 deferred = jQuery.Deferred() //轉(zhuǎn)成deferred對象 deferred.promise(jqXHR).complete = completeDeferred.add return jqXHR }
jQuery.ajax 的版本迭代:
為了向后兼容 XMLHttpRequest ,jqXHR 對象將公開下列屬性和方法:
readyState status statusText responseXML and/or responseText 當(dāng)?shù)讓拥恼埱蠓謩e作出XML和/或文本響應(yīng) setRequestHeader(name, value) 從標(biāo)準(zhǔn)出發(fā),通過替換舊的值為新的值,而不是替換的新值到舊值 getAllResponseHeaders() getResponseHeader() abort()
為了實(shí)現(xiàn)以上這些功能,jQuery 在對 jqXHR 做2個處理:
// Deferreds deferred = jQuery.Deferred(), //所有的回調(diào)隊(duì)列,不管任何時候增加的回調(diào)保證只觸發(fā)一次 completeDeferred = jQuery.Callbacks("once memory"),
給 jqXHR 擴(kuò)充添加 promise 的屬性和方法,然后添加 complete 方法,這里用的是回調(diào)列表的 add 方法(即添加回調(diào))
deferred.promise(jqXHR).complete = completeDeferred.add;
此時的 jqXHR 就具有了 promise 的一些特性了與 callback 的回調(diào)列隊(duì)了,當(dāng)然這里有個重點(diǎn),返回了一個只讀的 deferred 對象,如果返回完整的 deferred 對象,那么外部程序就能隨意的觸發(fā) deferred 對象的回調(diào)函數(shù),很有可能在 AJAX 請求結(jié)束前就觸發(fā)了回調(diào)函數(shù)(resolve),這就是與 AJAX 本身的邏輯相違背了。所以為了避免不經(jīng)意間改變?nèi)蝿?wù)的內(nèi)部流程,我們應(yīng)該只返回 deferred 的只讀版本 deferred.promise(),然后把對應(yīng)的 done 與 fail 改成別名 success 與 error。
jqXHR.success = jqXHR.done; jqXHR.error = jqXHR.fail
我們還需要把用戶自定的內(nèi)部回調(diào)函數(shù)給注冊到 jqXHR 對象上。
// 增加回調(diào)隊(duì)列 for (i in { success : 1, error : 1, complete : 1 }) { /** * 把參數(shù)的回調(diào)函數(shù)注冊到內(nèi)部jqXHR對象上,實(shí)現(xiàn)統(tǒng)一調(diào)用 * 給ajax對象注冊 回調(diào)函數(shù)add * deferred返回complete,error外部捕獲 */ jqXHR[i](s[i]); }
通過一個 for 循環(huán)把對應(yīng)的方法都執(zhí)行了,具體就是這幾個:
我們參考右邊 Ajax 的模擬實(shí)現(xiàn)代碼。
請驗(yàn)證,完成請求
由于請求次數(shù)過多,請先驗(yàn)證,完成再次請求
打開微信掃碼自動綁定
綁定后可得到
使用 Ctrl+D 可將課程添加到書簽
舉報(bào)