最近研究运行对象,稍微总结一下,以后继续补充:
Deferred是jQuery中对CommonJS的异步模型现实,旨在供给通用的接口,简化异步编程难度。
其是一个可链式作操的对象,供给多个调回函数的册注,以及调回队列的调回,并传达任何异步作操胜利或失败的息消。
由于其对jQuery Callbacks的依赖性,如果没有观点的友朋可以查看jQuery Callbacks。
jQuery.Deferred( [beforeStart ] )
建创一个Deferred对象。
beforeStart:
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; };
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对象中的then
, done
, fail
, always
, pipe
. isResolved
, 和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就是这样把广大劳动人民吸引过来的。今天的结果你们都看到了。)