运行对象jQuery Deferred

最近研究运行对象,稍微总结一下,以后继续补充:

    Deferred是jQuery中对CommonJS的异步模型现实,旨在供给通用的接口,简化异步编程难度。

    其是一个可链式作操的对象,供给多个调回函数的册注,以及调回队列的调回,并传达任何异步作操胜利或失败的息消。

    由于其对jQuery Callbacks的依赖性,如果没有观点的友朋可以查看jQuery Callbacks

 

    

jQuery.Deferred( [beforeStart ] )

    

    建创一个Deferred对象。

    beforeStart:

    

类型:  Function Deferred deferred )

    

一个在构造函数返回前运行的处置函数。

    

 

    

resolve、reject、notify

    Defferred中义定了三种动作,resolve(决解)、reject(绝拒)、notify(通知),对应Callbacks对象的fire动作。

    进而又供给了可以义定运行时的this对象的fire,即fireWith,所以又有扩展了三个对应的作操resolveWith、rejectWith、notifyWith。

    外部对应的事件分离是:done(作操成完)、fail(作操失败)、progress(作操进行中),也就是Callbacks对象的add方法添加听监。

    

    举个单简的例子,我们可以通过deferred.done册注上一个动作成完后的,那么当有方地触发了deferred.resolve或者deferred.resolveWith(这两个方法的别差在于能不能义定调回函数的this对象)时,则调回册注的函数。

    其他对应的也是一样的。

    

    代码上大概是这样的:

var dtd = $.Deferred(); // 建新一个deferred对象
var wait = function(dtd){
    var tasks = function(){
        alert("执行终了!");
        dtd.resolve(); // 转变deferred对象的执行态状
        };
    setTimeout(tasks,5000);
    return dtd;
};
这样我们就有了一个5000ms延迟的wait函数。于是我们就能够这么调用:
wait(dtd).done(function(){ alert("胜利了!"); })
               .fail(function(){ alert("犯错啦!"); });
 

    

then

    then方法供给了三种事件的册注,只要按序顺作为数参传进去就能够了。

then: function( /* fnDone, fnFail, fnProgress */ ) {
    //分离对应成完后运行的函数,失败后运行的函数,正在运行中程过运行的函数
    var fns = arguments;
    //返回一个新的Deferred的promise,then是上一个Deferred运行后才运行的
    return jQuery.Deferred(function( newDefer ) {
        //分离对不同态状册注函数
        jQuery.each( tuples, function( i, tuple ) {
            var action = tuple[ 0 ],    //掏出动作名
            fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];    //掏出对应调回函数
            // 分离对以后的Deferred对象册注调回函数,也就是册注deferred[ done | fail | progress ]
            deferred[ tuple[1] ](function() {
                var returned = fn && fn.apply( this, arguments );
                //如果传进来的调回函数会返回Deferred对象则在该对象上册注事件
                if ( returned && jQuery.isFunction( returned.promise ) ) {
                    returned.promise()
                        .done( newDefer.resolve )
                        .fail( newDefer.reject )
                        .progress( newDefer.notify );
                //否则对建创出来的newDefer执行对应事件
                } else {
                    //如果上一个函数有返回值则接受传返回值,否则传上一个Deferred传来的数参
                    newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
                }
            });
        });
        fns = null;
    }).promise();
},
 

    

Promise

    

    Promise只供给Deferred对象中的thendonefailalwayspipeisResolved, 和isRejected,避免用户自行转变Deferred的态状。

    

 

    完全的Deferred

    每日一道理
成熟是一种明亮而不刺眼的光辉,一种圆润而不腻耳的音响,一种不需要对别人察颜观色的从容,一种终于停止了向周围申诉求告的大气,一种不理会哄闹的微笑,一种洗刷了偏激的淡漠,一种无须声张的厚实,一种并不陡峭的高度。
jQuery.Deferred = function( func ) {
    var tuples = [
            // 动作, 听监事件, 调回函数队列, 终究态状
            [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
            [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
            [ "notify", "progress", jQuery.Callbacks("memory") ]
        ],
        state = "pending",
        //义定promise对象
        promise = {
            //返回以后态状
            state: function() {
                return state;
            },
            //无论胜利还是失败都运行调回函数
            always: function() {
                deferred.done( arguments ).fail( arguments );
                return this;
            },
            then: function( /* fnDone, fnFail, fnProgress */ ) {
            //分离对应成完后运行的函数,失败后运行的函数,正在运行中程过运行的函数
                var fns = arguments;
                //返回一个新的Deferred的promise,then是上一个Deferred运行后才运行的
                return jQuery.Deferred(function( newDefer ) {
                    //分离对不同态状册注函数
                    jQuery.each( tuples, function( i, tuple ) {
                        var action = tuple[ 0 ],    //掏出动作名
                            fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];    //掏出对应调回函数
                        // 分离对以后的Deferred对象册注调回函数,也就是册注deferred[ done | fail | progress ]
                        deferred[ tuple[1] ](function() {
                            var returned = fn && fn.apply( this, arguments );
                            //如果传进来的调回函数会返回Deferred对象则在该对象上册注事件
                            if ( returned && jQuery.isFunction( returned.promise ) ) {
                                returned.promise()
                                    .done( newDefer.resolve )
                                    .fail( newDefer.reject )
                                    .progress( newDefer.notify );
                            //否则对建创出来的newDefer执行对应事件
                            } else {
                                //如果上一个函数有返回值则接受传返回值,否则传上一个Deferred传来的数参
                                newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
                            }
                        });
                    });
                    fns = null;
                }).promise();
            },
            // 如果deferred存在,将promise合并到deferred里,否则返回prmoise
            promise: function( obj ) {
                return obj != null ? jQuery.extend( obj, promise ) : promise;
            }
        },
        deferred = {};
    // 向后兼容
    promise.pipe = promise.then;

    // 对deferred添加余剩的方法
    jQuery.each( tuples, function( i, tuple ) {
        //掏出对应队列
        var list = tuple[ 2 ],
            //掏出对应态状
            stateString = tuple[ 3 ];
        // 予赋promise[ done | fail | progress ] = list.add
        promise[ tuple[1] ] = list.add;
        // 对态状添加事件处置
        if ( stateString ) {
            list.add(function() {
                // 态状state = [ resolved | rejected ]
                state = stateString;
            // 禁用对各队列[ reject_list | resolve_list ].disable; progress_list.lock
            }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
        }

        // 分离册注方法deferred[ resolve | reject | notify ]
        deferred[ tuple[0] ] = function() {
            deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
            return this;
        };
        // 册注有with的方法
        deferred[ tuple[0] + "With" ] = list.fireWith;
    });

    // 将promise中的方法合并到deferred里
    promise.promise( deferred );

    // 如果jQuery.Deferred中的数参存在,则先用这个数参对deferred造改
    if ( func ) {
        func.call( deferred, deferred );
    }

    // 成完
    return deferred;
};
 

    

jQuery.when

    jQuery.when是一个帮助Deferred队列处置的具工,如果传单一Deferred进去,则会返回其promise,如果传多个Deferred进去,则会建新一个Deferred用以管理该Deferred队列。

    

    

  • 如果队列中有一个Deferred失败,则个整队列失败。
  • 如果队列中有所Deferred胜利,则个整队列胜利。
  • 如果队列中有所Deferred开始运行,则个整队列正在运行。 

    

jQuery.when = function( subordinate /* , ..., subordinateN */ ) {
    var i = 0,
        //将arguments转成数组
        resolveValues = core_slice.call( arguments ),
        //传入Deferred对象总数
        length = resolveValues.length,

        // 未成完的Deferred总数
        remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,

        // Deferred队列管理器,如果数参只有一个Deferred则返回该Deferred
        deferred = remaining === 1 ? subordinate : jQuery.Deferred(),

        // 更新resolve和progress的Deferred数量,全体处在这两个态状则通知管理器
        updateFunc = function( i, contexts, values ) {
            return function( value ) {
                contexts[ i ] = this;
                values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;
                if( values === progressValues ) {
                    deferred.notifyWith( contexts, values );
                } else if ( !( --remaining ) ) {
                    deferred.resolveWith( contexts, values );
                }
            };
        },

        progressValues, progressContexts, resolveContexts;

    // 如果传入Deferred总量大于1,则添加事件处置
    if ( length > 1 ) {
        progressValues = new Array( length );
        progressContexts = new Array( length );
        resolveContexts = new Array( length );
        for ( ; i < length; i++ ) {
            //断判数参是不是可用的Deferred
            if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
                resolveValues[ i ].promise()
                    //单个胜利则更新胜利数
                    .done( updateFunc( i, resolveContexts, resolveValues ) )
                    //单个失败则个整队列失败
                    .fail( deferred.reject )
                    //单个开始运行则更新运行中的个数
                    .progress( updateFunc( i, progressContexts, progressValues ) );
            //不可用则未成完数减1
            } else {
                --remaining;
            }
        }
    }

    // 如果没有任何可用Deferred则直接通知管理器,队列成完
    if ( !remaining ) {
        deferred.resolveWith( resolveContexts, resolveValues );
    }

    //返回Promise
    return deferred.promise();
};

    其主要通过置内一个Deferred来管理队列的运行态状,不过其只将Promise暴露在外,而用闭包将有所Deferred护保起来。 

    

文章结束给大家分享下程序员的一些笑话语录: 苹果与谷歌之争就是封闭收费与自由免费思想之争。(别急着把google来膜拜哦?那可是一家公司,以赚钱为目标的公司!当年我Party就是这样把广大劳动人民吸引过来的。今天的结果你们都看到了。)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值