亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

章節
問答
課簽
筆記
評論
占位
占位

Deferred源碼剖析(下)

在上一節中構建了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 可將課程添加到書簽

邀請您關注公眾號
關注后,及時獲悉本課程動態

舉報

0/150
提交
取消
全部 精華 我要發布
全部 我要發布
最熱 最新
只看我的

手記推薦

更多

本次提問將花費2個積分

你的積分不足,無法發表

為什么扣積分?

本次提問將花費2個積分

繼續發表請點擊 "確定"

為什么扣積分?