jquery异步机制源码分析
16lz
2021-01-22
统揽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 );
}
流程分析
- 调用resolve时,相当与调用resolveWidth,相当于调用fireWith
- fireWith即执行通过done回调函数或者then添加进来的方法,底层用Callbacks.add添加回调,且按照回调的添加顺序执行
- 若then中的回调方法返回deferred对象,就用此返回的对象的resolve替换父级deferred中的resolve。
更多相关文章
- jQuery对象和DOM对象
- 整理:Google jQuery 引用地址大全和方法(转)
- 如何修复JSON对象的假数组?
- 如何使用ajax GET或POST方法将数据传递到amazon lambda节点。js
- Jquery常用技巧和方法收集
- Chosen 基于jquery的选择框插件使用方法
- jQuery $ajax 传中文数据到action乱码解决方法
- JQuery 的选取元素 和 方法
- jquery的function方法中each循环里面判断失败跳出function方法