jQuery Deferred

来源:互联网 发布:windows编程视频 编辑:程序博客网 时间:2024/04/30 06:44

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保护起来。 



源引:http://www.cnblogs.com/justany/archive/2013/01/20/2867444.html



0 0
原创粉丝点击