var tuples = [
  // action , add listener, listener list, final state
  [ 'resolve', 'done', jQuery.Callbacks('once memory'), 'resoved' ],
  [ 'reject', 'fail', jQuery.Callbacks('once memory'), 'rejected'],
  [ 'notify', 'progress', jQuery.Callbacks('memory')]
];

 

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

jQuery.each( tuples, function( i, tuple ){
  //当第一次循环时,i = 0 tuple = ["resolve", "done", {…}, "resoved"];
  var list = tuple[2];         //存的是self这个回调对象
  var stateString = tuple[3]     //存的是resolved rejected两个状态
  promise[ tuple[1] ] = list.add;    //向promise对象中添加三个方法
  if( stateString ){
    list.add( function one(){
    state = stateString;
    }, tuples[ i ^ 1 ][ 2 ].disable, tuples[2][2].lock )
  }
  defered[ tuple[0] ] = function(){
    defered[ tuple[0] + 'With' ]( this === defered ? defered : promise, arguments );
    return this;
  };
  defered[ tuple[0] + 'With' ] = list.fireWith; 
})

个人感悟: Deferred实现研究了大概三天,从中发现很多细节之处,也是对Js这门语言的基础了解不够深入,万丈高楼平地起,所以基础很关键啊

先来看一段代码

function fn(){
  var list = [1,2,3,4,5],
  obj = {
    disable: function(){
      list = undefined;

      return this;
    },
    show:function(){
      return list;
    }
  }
  return obj;
}

var res1 = fn();

var res2 = fn();

res1.disable().show()  //undefined

res2.show()                //[1,2,3,4,5]

其实想表达的就是,res1 res2得到的是两个不同的环境,第一次调用disable() 修改的是res1这个环境的list变量,但是不会影响res2这个环境下的list变量 ,再回头看Dererred

只拿第一次循环为例

i = 0; list = {  /* 这个就是jQuery.Callbacks('once memory')这个工厂函数返回的对象 */  }; stateString = 'resolved'; promise[ 'done' ] = list.add ; deferred['resolve'] = fn = list.fireWith  /*注意这个add, fireWith是当前工厂函数返回对象下的函数*/ 

list.add( fn1, fn2, fn3 )  第一个函数只是修改状态,第二个函数是第二个list下的disable,第三个函数是第三个list下的lock,每个Callbacks(这里需要对callbacks源码有理解)函数下的list数组中都会出现三个函数存在

为了当触发resolve的时候,状态改变,就不能再变了,也就是说不能在调用reject了,因为此时已经被disable了

通过jquery.extend( obj, promise )方法把promise下的所有方法深拷贝到obj下 也就是deferred对象下 /*此处代码没写,可自行在源码中查看 在promise对象下的promise方法中实现*/

当 var dfd = $.Deferred();   //创建一个延迟对象

        dfd.done( function(){ console.log('successs') } )  // 当调用done时,间接调用list.add,那么必然调用的是第一个list下的add, 因为done与第一个list下的add是同一个引用关系,所以执行的是第一个add函数所在的环境

     dfd.resolve()  //此时间接调用了list.fireWith 此时的list与上面的add是同一个list对象  然后开始循环触发 callbacks工厂函数内的 list = [ fn1, fn2, fn3, fn4 ]  /*此时内部有3 + 1个函数*/ 

讲到这里该结束了,如有问题之处,希望大家可以指出,一起学习进步

 

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄