jquery中的 deferred之 then (二)

例:

var def = $.Deferred();
var prs1 = def.then(function (val) {
var result = val + "_123"
console.log(result);// 0_123
return result;;
});
var prs2 = prs1.then(function (val) {
var result = val + "_234"
console.log(result);// 0_123_234
return result;
});
var prs3 = prs2.then(function (val) {
var result = val + "_345"
console.log(result);// 0_123_234_345
return result;
});
def.resolve("0");

核心源码分析:

then: function( /* fnDone, fnFail, fnProgress */ ) {
var fns = arguments;
return jQuery.Deferred(function (newDefer) { //20170620 huanhua 当调用 jQuery.Deferred(参数) 参数不为空的时候,参数必须是 包含 $.Deferred()对象参数的函数
//if ( func ) { func.call( deferred, deferred );} 详见下面这段代码。
jQuery.each(tuples, function (i, tuple) {
var action = tuple[ 0 ],
fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
// deferred[ done | fail | progress ] for forwarding actions to newDefer
deferred[ tuple[1] ](function() {
var returned = fn && fn.apply(this, arguments);
//20170620 huanhua 如果then方法传递的参数 [fnDone, fnFail, fnProgress],其中的函数如果返回的是 Defferred对象。
if (returned && jQuery.isFunction(returned.promise)) {
//20170620 huanhua 此时注册的 done/fail/progess 就是传入的 Defferred对象已经注册好了的对象
//20170624 huahua returned是一个 deferred,在 fn 里面,必须要调用 deferred.resolve/deferred.reject/deferred.notify
//否则不会 触发 newDefer.resolve/newDefer.reject/newDefer.notify
returned.promise()
.done( newDefer.resolve )
.fail( newDefer.reject )
.progress( newDefer.notify );
} else {
newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
}
});
});
fns = null;
}).promise();
},

里面最核心的一段代码,如下这段代码能看懂基本就看懂了 then了:

deferred[ tuple[1] ](function() {
var returned = fn && fn.apply(this, arguments);
//20170620 huanhua 如果then方法传递的参数 [fnDone, fnFail, fnProgress],其中的函数如果返回的是 Defferred对象。
if (returned && jQuery.isFunction(returned.promise)) {
//20170620 huanhua 此时注册的 done/fail/progess 就是传入的 Defferred对象已经注册好了的对象
//20170624 huahua returned是一个 deferred,在 fn 里面,必须要调用 deferred.resolve/deferred.reject/deferred.notify
//否则不会 触发 newDefer.resolve/newDefer.reject/newDefer.notify
returned.promise()
.done( newDefer.resolve )
.fail( newDefer.reject )
.progress( newDefer.notify );
} else {
newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
}
});

首先我们看一个案例:

var Person = function () {
var listdo = [];
var parValue = "";
this.fire = function (value) {
parValue = value;
for (var xh in listdo) {
listdo[xh](value);
}
};
this.do = function (fn) {
var prs = new Person();
if (typeof fn === "function") {
listdo.push(fn);
}
listdo.push(function () { prs.fire(parValue); });
return prs;
}
};
var person1 = new Person();
person1.do(function (val) { alert("孩子们:" + val); })
.do(function (val) { alert("孙子们:" + val); })
.do(function (val) { alert("重孙们:" + val); });
person1.fire("操练起来!!!");

这段代码中有一个祖孙的链式关系,通过闭包来实现的,分析见图2。

图2:jquery中的 deferred之 then (二)

这个思路很重要,也是 then 实现的核心思想。

在then的源代码中有这么一段代码:

// deferred[ done | fail | progress ] for forwarding actions to newDefer
deferred[ tuple[1] ](function() {

deferred[tuple[1]]就是在给 deferred[done|fail|progess]添加执行的方法

newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );

这段代码就是添加的执行链式中下一个对象的方法。returned或者arguments就是传递到链式中下一个要执行的对象中的方法的参数。

如果这些都看懂了,then的实现原理就明白了,实现了一个按照 then添加的先后顺序进行执行的功能。

上一篇:GIS大数据存储预研


下一篇:jQuery刮彩票兑奖效果