在上一節中構建了deferred對象,實現了done/fail/process和resolve/reject/notify等方法,但是最重要的then,pipe管道接口我們還沒有實現,我們考慮下:
var dfd = $.Deferred() dfd.then(function(preVale) { return 2 * preVale //4 }).then(function(preVale) { return 3 * preVale //12 }) dfd.resolve(2)
then就是pipe,我們可以想象是一個管道,可以對回調模式使用瀑布模型。如案例所示,下一個回調都能取到上一個回調的值,這樣一直可以疊加往后傳遞。
不難看出管道的風格就是鏈式的操作,每一個鏈上的結果都會反饋后下一個鏈,那么這個鏈式是不是傳統的返回自身這個對象this呢?
常規的辦法通過數組處理:右側代碼所示。
function aDeferred(){ //代碼右側代碼 }
這樣的結構當然是很簡陋的,這里我們最終有一個本質的問題沒有解決,jQuery中的then的返回還有可能是另一個新的異步模型對象,如ajax,因此還能實現done,fail,always,then等方法。所以采用簡陋的數組的方式保存狀態是很膚淺的了。
這時候jQuery采取了對象保存處理:
我們可以把每一次的then操作,當做是創建一個新的deferred對象,那么每一個對象都夠保存自己的狀態與各自的處理方法。通過一個辦法把所有的對象操作都串聯起來,這就是then或者pipe管道設計的核心思路了。
看jQuery的then結構:
then: function( /* fnDone, fnFail, fnProgress */ ) { var fns = arguments; return jQuery.Deferred(function(newDefer) { jQuery.each(tuples, function(i, tuple) { deferred[tuple[1]](function() { // deferred[ done | fail | progress ] }); }); }).promise()
其實在內部創建了一個新的Deferred對象,不過這里的不同是通過傳遞一個回調函數,參數是newDefer,其實Deferred內部就是為了改變下上下文this為deferred,然后傳遞deferred給這個回調函數了,所以newDefer就指向內部的deferred對象了。
那么對象之間如何關聯?
jQuery.each(tuples, function(i, tuple) { //取出參數 var fn = jQuery.isFunction(fns[i]) && fns[i]; // deferred[ done | fail | progress ] for forwarding actions to newDefer // 添加done fail progress的處理方法 // 針對延時對象直接做了處理 deferred[tuple[1]](function() { var returned = fn && fn.apply(this, arguments); if (returned && jQuery.isFunction(returned.promise)) { returned.promise() .done(newDefer.resolve) .fail(newDefer.reject) .progress(newDefer.notify); } else { newDefer[tuple[0] + "With"](this === promise ? newDefer.promise() : this, fn ? [returned] : arguments); } });
把then的方法通過:
deferred.done deferred.fail deferred.progress
加入到上一個對象的各自的執行隊列中保存了。這樣就實現了不同對象之間的關聯調用。
同樣如果then返回的是一個promise對象(ajax)的時候:
if (returned && jQuery.isFunction(returned.promise)) { returned.promise() .done(newDefer.resolve) .fail(newDefer.reject) .progress(newDefer.notify);
也可以直接處理了。
請驗證,完成請求
由于請求次數過多,請先驗證,完成再次請求
打開微信掃碼自動綁定
綁定后可得到
使用 Ctrl+D 可將課程添加到書簽
舉報