例:promise
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了:app
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:this
這個思路很重要,也是 then 實現的核心思想。spa
在then的源代碼中有這麼一段代碼:code
// 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就是傳遞到鏈式中下一個要執行的對象中的方法的參數。blog
若是這些都看懂了,then的實現原理就明白了,實現了一個按照 then添加的前後順序進行執行的功能。