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