jquery中的 deferred之 then (二)

例: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添加的前後順序進行執行的功能。

相關文章
相關標籤/搜索