深く分析して、jQuery.を理解しますDeferredソース
18193 ワード
前言:もしあなたがjQuery.にCallbackコールバックの対象がわからない、あるいはその方法しか把握していないが、ソースコードを読むことで理解できず、先に読むことができる
前章jQuery.Callbacksソースコード解読2は、jQueryを完全に理解するしかないからです.Callbackソースコードは、jQueryを本当に理解し、把握することができます.Deferred繰延オブジェクト.
ソース:
完全なインスタンス1:
1つ目の使い方:
resolveを呼び出すと、fn 1はjQueryのため実行されません.Callbacks('once memory')コールバックオブジェクトからの着信フラグonce
2つ目の書き方:
上の書き方は対応するjQuery.Callbacks('once memory')コールバックオブジェクトにフラグmemoryが入力され、コールバックがトリガーされます.
次の操作はfailのため機能しません.reject操作に対応するコールバックオブジェクトが無効になっています.
以下の操作も機能しません.progressのため、notify操作に対応するコールバックオブジェクトがロックされています.ここで疑問なのは、なぜソースコードの3番目のコールバックオブジェクトが無効ではなくロックされているのかということです.転送されたflagにはmemoryがないため、実行ロックは実際には無効です.
完全なインスタンス2:
fn 4は、thenでnewDeferが実行されているため、なぜ実行されるのか.ファイルはnewDeferですpromiseオブジェクト、および対応するjQuery.Callbacks('once memory')コールバックオブジェクトにフラグmemoryが入力されました.再び、結果の最初のサブ列はなぜundefinedなのか、thenでは関数が渡されているため、この関数は戻り値を表示せず、デフォルトではundefinedが返されます.
逆にthenにパラメータが伝達されていない場合、コールバックはresolveから伝達されたパラメータを取得することができる.
完全なインスタンス3:
転載は出典を明記してください:ブログ園華子yjh
前章jQuery.Callbacksソースコード解読2は、jQueryを完全に理解するしかないからです.Callbackソースコードは、jQueryを本当に理解し、把握することができます.Deferred繰延オブジェクト.
ソース:
// jQuery 1.10.2
jQuery.extend({
Deferred: function( func ) {
/*
tuples
jQuery fire, add, jQuery.Callbacks( flag ),
deferred[ resolve | resolveWith | done ],promise[ done ] ,
deferred[ reject | rejectWith | fail ],promise[ fail ] ,
deferred[ notify | notifyWith | progress ] , 。
,then 。
: deferred promise jQuery.Deferred , then , deferred promise
: var df = $.Deferred(); var df2 = df.then(args); df2( promise) newDefer( deferred) ,
, then 。
*/
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") ]
],
state = "pending",
promise = {
state: function() {
return state;
},
always: function() {
deferred.done( arguments ).fail( arguments );
return this;
},
then: function( /* fnDone, fnFail, fnProgress */ ) {
var fns = arguments;
return jQuery.Deferred(function( newDefer ) {
// this === deferred; // true;
jQuery.each( tuples, function( i, tuple ) {
var action = tuple[ 0 ],
fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
// deferred[ done | fail | progress ] for forwarding actions to newDefer
deferred[ tuple[1] ](function() {
// ,fn
var returned = fn && fn.apply( this, arguments );
/*
:
1、fn then; 2、fn Deferred; 1,2
3、 fn , returned === deferred
jQuery.Callbacks add , firingLength,
newDefer[ resolve | reject | notify ] , fn.apply( this, arguments )
*/
if ( returned && jQuery.isFunction( returned.promise ) ) {
returned.promise()
.done( newDefer.resolve )
.fail( newDefer.reject )
.progress( newDefer.notify );
}
/*
deferred[ resolve | reject | notify ]
deferred[ resolve | reject | notify ] , promise( this), newDefer.promise
then , ( ), deferred[ resolve | resolveWith ]
*/
else {
// [ returned ], apply
newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
}
});
});
fns = null;
}).promise();
},
// Get a promise for this deferred
// If obj is provided, the promise aspect is added to the object
promise: function( obj ) {
return obj != null ? jQuery.extend( obj, promise ) : promise;
}
},
deferred = {};
// Keep pipe for back-compat
// , pipe
promise.pipe = promise.then;
// Add list-specific methods
jQuery.each( tuples, function( i, tuple ) {
var list = tuple[ 2 ],
stateString = tuple[ 3 ];
// promise[ done | fail | progress ] = list.add
promise[ tuple[1] ] = list.add;
// Handle state
// tuples , , ,
// , state = 'resolved', reject, fail ,
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[ resolve | reject | notify ] ( deferred.resolve.call( , args); ),
promise ,
*/
deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
return this;
};
deferred[ tuple[0] + "With" ] = list.fireWith;
});
// Make the deferred a promise
// deferred, promise
promise.promise( deferred );
// Call given func if any
// deferred.then
if ( func ) {
func.call( deferred, deferred );
}
// All done!
return deferred;
}
});
完全なインスタンス1:
var fn1 = function(){
console.log('resolved');
},
fn2 = function(){
console.log('rejected');
},
fn3 = function(){
console.log('pending');
};
var defer = $.Deferred();
1つ目の使い方:
1 defer.done(fn1);
2 defer.resolve(); // resolved
resolveを呼び出すと、fn 1はjQueryのため実行されません.Callbacks('once memory')コールバックオブジェクトからの着信フラグonce
1 defer.resolve(); // fn1
2つ目の書き方:
1 defer.resolve();
2 // defer.done(fn1).done(fn1).done(fn1);
3 defer.done(fn1); // resolved
4 defer.done(fn1); // resolved
5 defer.done(fn1); // resolved
上の書き方は対応するjQuery.Callbacks('once memory')コールバックオブジェクトにフラグmemoryが入力され、コールバックがトリガーされます.
次の操作はfailのため機能しません.reject操作に対応するコールバックオブジェクトが無効になっています.
1 defer.fail(fn2);
2 defer.reject();
以下の操作も機能しません.progressのため、notify操作に対応するコールバックオブジェクトがロックされています.ここで疑問なのは、なぜソースコードの3番目のコールバックオブジェクトが無効ではなくロックされているのかということです.転送されたflagにはmemoryがないため、実行ロックは実際には無効です.
1 defer.progress(fn3);
2 defer.notify();
完全なインスタンス2:
var fn1 = function(str){
console.log(str + ':' + 'resolved');
},
fn2 = function(str){
console.log(str + ':' + 'rejected');
},
fn3 = function(str){
console.log(str + ':' + 'pending');
},
fn4 = function(str){
console.log(str + ':' + 'resolved' + ' ' + 'again');
},
defer, filterd, filterd2;
defer = $.Deferred();
defer.resolve('state');
filterd = defer.then(fn1); // state:resolved
filterd.done(fn4); // undefined:resolved again
fn 4は、thenでnewDeferが実行されているため、なぜ実行されるのか.ファイルはnewDeferですpromiseオブジェクト、および対応するjQuery.Callbacks('once memory')コールバックオブジェクトにフラグmemoryが入力されました.再び、結果の最初のサブ列はなぜundefinedなのか、thenでは関数が渡されているため、この関数は戻り値を表示せず、デフォルトではundefinedが返されます.
逆にthenにパラメータが伝達されていない場合、コールバックはresolveから伝達されたパラメータを取得することができる.
1 filterd2 = defer.then();
2 filterd2.done(fn4); // state:resolved again
完全なインスタンス3:
var fn1 = function(str){
console.log(str + ':' + 'resolved');
//
return defer;
},
fn4 = function(str){
console.log(str + ':' + 'resolved' + ' ' + 'again');
},
defer, filterd;
defer = $.Deferred();
defer.resolve('state');
filterd = defer.then(fn1); // state:resolved
filterd = defer.done(fn4); // state:resolved again
転載は出典を明記してください:ブログ園華子yjh