jquery v_2.3.0 Deferred核心源码理解
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个函数*/
讲到这里该结束了,如有问题之处,希望大家可以指出,一起学习进步
