• 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:

    这个思路很重要,也是 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添加的先后顺序进行执行的功能。

  • 相关阅读:
    @ControllerAdvice + @ExceptionHandler 使用
    将博客搬至CSDN
    Docker pull网络错误
    Centos7.5安装Docker
    Oracle18c创建不带C##的用户
    Centos7.5静默安装Oracle18c
    nodeJs和JavaScript的异同
    maven项目引入本地包,不使用中央仓库
    java中把指数形式的数字转为正常形式显示
    validateJarFile jar not loaded. See Servlet Spec 2.3, section 9.7.2. Offending class: javax/servlet/Servlet.class
  • 原文地址:https://www.cnblogs.com/huaan011/p/7074341.html
Copyright © 2020-2023  润新知