统揽Deferred全局,如下:

1.  Deferred: function( func ) {
var tuples = [],
state = "pending",
promise = {
state: function() {},
always: function() {},
then: function() {},
promise: function( obj ) {}
},
deferred = {};
promise.pipe = promise.then;

jQuery.each( tuples, function( i, tuple ) {});
promise.promise( deferred );
if ( func ) {
func.call( deferred, deferred );
}
return deferred;
}

2. 可以看出,Deferred中有一个promise对象,Deferred最后返回deferred对象,deferred对象刚开始被定义为空对象,那么什么时候为其赋值呢?请看jQuery.each( tuples, function( i, tuple ) {});这一行代码中的内容,其中涉及tuples定义:

var tuples = [
// action, add listener, listener list, final state
[ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
[ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
[ "notify", "progress", jQuery.Callbacks("memory") ]
];

3.再看jQuery.each( tuples, function( i, tuple ) {});

jQuery.each( tuples, function( i, tuple ) {
var list = tuple[ 2 ],// jQuery.Callbacks("once memory")
stateString = tuple[ 3 ];

//即将jQuery.Callbacks.add赋值给promise的done | fail | progress回调,至此,promise的方法又多了3个
promise[ tuple[1] ] = list.add;

//若stateString 有值,就向done_list或者failed_list中传入3个回调函数
if ( stateString ) {
list.add(

//第1个回调:将当前状态变为 [ resolved | rejected ],初始状态为pending,若list为done ,就将其状态置为resolved
function() {
state = stateString;
},

//第2个回调:将对应状态中list.add添加的回调disable,若list为done ,就将fail中jQuery.Callbacks("once memory")添加的回调disable
tuples[ i ^ 1 ][ 2 ].disable,

//第3个回调:锁定当前Callbacks
tuples[ 2 ][ 2 ].lock );
}

// deferred[ resolve | reject | notify ]
deferred[ tuple[0] ] = function() {
deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
return this;
};
deferred[ tuple[0] + "With" ] = list.fireWith;
});

4.接下来是promise.promise( deferred );这段代码的作用是将 promise中的方法扩展到当前的deferred中,

promise.promise: function( obj ) {
return obj != null ? jQuery.extend( obj, promise ) : promise;
}

因此,现在的deferred中的方法有:

always:()
done:()
fail:()
notify:()
notifyWith:( context, args )
pipe:( /* fnDone, fnFail, fnProgress */ )
progress:()
promise:( obj )
resolve:()
reject:()
rejectWith:resolve:()
resolveWith:( context, args )
state:()
then:( /* fnDone, fnFail, fnProgress */ )
__proto__:Object

这就是最终返回的deferred对象包含的方法。

5.下面分析then方法

then: function() {
return jQuery.Deferred(function( newDefer ) {}).promise();
}

先看then方法的骨架,其返回的是当前Deferred中的promise对象,不是deferred对象。then方法递归调用jQuery.Deferred(func ),且通过then方法进入jQuery.Deferred(func )时,func不为空,因此,执行

if ( func ) {
func.call( deferred, deferred );
}

此时,deferred为从then中进入的jQuery.Deferred(func )返回的deferred对象,相当于下面的newDefer,即进入then方法内部jQuery.Deferred(func )中执行func,即下面的方法:

var fns = arguments;//then方法的参数, fnDone, fnFail, fnProgress 
function( newDefer ) {
jQuery.each( tuples, function( i, tuple ) {
var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];//将此处看成fnDone

// 向deferred[ done | fail | progress ] 中添加对应的回调,此处的deferred是父Deferred中的对象
deferred[ tuple[1] ](

//回调函数开始
function(){}
//回调函数结束

);
});
fns = null;
}

下面分析向父deferred对象中添加的回调函数

function(){

//returned为fnDone|fnFail的返回值,即then的回调函数返回值
var returned = fn && fn.apply( this, arguments );

//若returned.promise有值,就向returned.promise()返回的当前promise对象的3个回调函数中分别添加父级deferred的3个方法,相当于returned对象在执行resolve时便执行newDefer.resolve,即父级deferred的resolve方法,即用新返回的returned中的resolve方法替换父级deferred的resolve方法
if ( returned && jQuery.isFunction( returned.promise ) ) {
returned.promise()
.done( newDefer.resolve )
.fail( newDefer.reject )
.progress( newDefer.notify );
} else {
//若returned不是promise对象,则父Deferred立即执行add进来的方法
newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
}

流程分析

  1. 调用resolve时,相当与调用resolveWidth,相当于调用fireWith
  2. fireWith即执行通过done回调函数或者then添加进来的方法,底层用Callbacks.add添加回调,且按照回调的添加顺序执行
  3. 若then中的回调方法返回deferred对象,就用此返回的对象的resolve替换父级deferred中的resolve。

更多相关文章

  1. jQuery对象和DOM对象
  2. 整理:Google jQuery 引用地址大全和方法(转)
  3. 如何修复JSON对象的假数组?
  4. 如何使用ajax GET或POST方法将数据传递到amazon lambda节点。js
  5. Jquery常用技巧和方法收集
  6. Chosen 基于jquery的选择框插件使用方法
  7. jQuery $ajax 传中文数据到action乱码解决方法
  8. JQuery 的选取元素 和 方法
  9. jquery的function方法中each循环里面判断失败跳出function方法

随机推荐

  1. Android Drawable缓存
  2. android之实现ProgressBar进度条组件
  3. Android 隐藏ActionBar
  4. Android 使用WebView控件展示SVG图
  5. 各种控件属性
  6. Android两种序列化方式详解(一):Serializabl
  7. 判断Android的WIFI与GPS状态,并引导用户前
  8. android 键盘 搜索键
  9. android 性能优化
  10. AgentWeb WebView 与 Android交互 JS调用