- 浏览: 3418 次
- 性别:
- 来自: 北京
文章分类
最新评论
function log(s) { $('body').append(s + '<br/>'); }
var value1, value2, value3,
defer = jQuery.Deferred();
defer
.done(function(){
// console.log("I am 1st done");
})
.done(function(a,b){
value1 = a;
value2 = b;
})
.done(function(a,b){
log("a = " + a);
log("b = " + b);
return a * b;
})
.done(function( result ) {
log("result = " + result);
value3 = result;
})
.then(function( a, b ) {
log("a = " + a);
log("b = " + b);
return a * b;
})
.done(function( result ) {
log("result = " + result);
value3 = result;
})
.then(function( a, b ) {
log("a = " + a);
log("b = " + b);
return a * b;
})
.done(function( result ) {
log("result = " + result);
value3 = result;
})
;
defer.resolve( 2, 3 );
上面這段代碼的輸出是:
a = 2
b = 3
result = 2
a = 2
b = 3
result = 6
a = 6
b = undefined
result = NaN
參見:http://jsfiddle.net/JqRc9/
then()和done().fail().process()的差別是
then: function( /* fnDone, fnFail, fnProgress */ )會生成一個新的deferred,return jQuery.Deferred(function( newDefer )。初始化這個新deferred時,執行function( newDefer ),這個function添加一個callback func到前一個deferred。這個callback func是從老deferred到新deferred的橋樑,從deferred[ tuple[1]]到newDefer[ tuple[0] + "With" ]。對於每個deferred[ tuple[1] ],如果有對應的then()所帶function( /* fnDone, fnFail, fnProgress 之一*/ ),這個函數就是
function () {
var returned = fn.apply( this, arguments );
if ( returned && jQuery.isFunction( returned.promise ) ) {
returned.promise()
.done( newDefer.resolve )
.fail( newDefer.reject )
.progress( newDefer.notify );
} else {
newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, [ returned ] );
}
}
then所帶函數會被執行,返回returned,如果jQuery.isFunction( returned.promise ),则调用这个returned.promise的done、fail和progress,它们会对应触发newDefer的resolve、reject、notify; 否则 returned 傳入新的deferred,newDefer执行action + “with”;
如果沒有對應的then()所帶函數,簡單執行newDefer[ action ]。
上面的第一個result是第一個result的最后一個done()的輸出,前一個done的return不會傳遞到這裡,所以result是resolve的第一個參數。
第二個result是第二個deferred的輸出,第一個then所帶的function的輸入,傳入第二個deferred,因此第五個done能夠接受到2*3的result。
第三個result是第三個deferred的輸出,第二個then執行時,只有a,沒有b,所以result是NaN。
更多的log如下:
start deferred.js:100
************************************************ deferred.js:101
deferred.key = 29814 -> tuple[1] = done jquery.js:1195
callback.key = 81354 jquery.js:1196
In callback[81354] ---- list.length to 1 jquery.js:1030
list.push = jquery.js:1031
function () {
// state = [ resolved | rejected ]
state = stateString;
// [ reject_list | resolve_list ].disable; progress_list.lock
} jquery.js:1032
In callback[81354] ---- list.length to 2 jquery.js:1030
list.push = jquery.js:1031
function () {
list = stack = memory = undefined;
return this;
} jquery.js:1032
In callback[81354] ---- list.length to 3 jquery.js:1030
list.push = jquery.js:1031
function () {
stack = undefined;
if ( !memory ) {
self.disable();
}
return this;
} jquery.js:1032
deferred.key = 29814 -> tuple[1] = fail jquery.js:1195
callback.key = 4458 jquery.js:1196
In callback[4458] ---- list.length to 1 jquery.js:1030
list.push = jquery.js:1031
function () {
// state = [ resolved | rejected ]
state = stateString;
// [ reject_list | resolve_list ].disable; progress_list.lock
} jquery.js:1032
In callback[4458] ---- list.length to 2 jquery.js:1030
list.push = jquery.js:1031
function () {
list = stack = memory = undefined;
return this;
} jquery.js:1032
In callback[4458] ---- list.length to 3 jquery.js:1030
list.push = jquery.js:1031
function () {
stack = undefined;
if ( !memory ) {
self.disable();
}
return this;
} jquery.js:1032
deferred.key = 29814 -> tuple[1] = progress jquery.js:1195
callback.key = 67133 jquery.js:1196
In callback[81354] ---- list.length to 4 jquery.js:1030
list.push = jquery.js:1031
function (){
// console.log("I am 1st done");
} jquery.js:1032
In callback[81354] ---- list.length to 5 jquery.js:1030
list.push = jquery.js:1031
function (a,b){
value1 = a;
value2 = b;
} jquery.js:1032
In callback[81354] ---- list.length to 6 jquery.js:1030
list.push = jquery.js:1031
function (a,b){
console.log("a = " + a);
console.log("b = " + b);
return a * b;
} jquery.js:1032
In callback[81354] ---- list.length to 7 jquery.js:1030
list.push = jquery.js:1031
function ( result ) {
console.log("result = " + result);
value3 = result;
} jquery.js:1032
deferred.key = 55257 -> tuple[1] = done jquery.js:1195
callback.key = 24912 jquery.js:1196
In callback[24912] ---- list.length to 1 jquery.js:1030
list.push = jquery.js:1031
function () {
// state = [ resolved | rejected ]
state = stateString;
// [ reject_list | resolve_list ].disable; progress_list.lock
} jquery.js:1032
In callback[24912] ---- list.length to 2 jquery.js:1030
list.push = jquery.js:1031
function () {
list = stack = memory = undefined;
return this;
} jquery.js:1032
In callback[24912] ---- list.length to 3 jquery.js:1030
list.push = jquery.js:1031
function () {
stack = undefined;
if ( !memory ) {
self.disable();
}
return this;
} jquery.js:1032
deferred.key = 55257 -> tuple[1] = fail jquery.js:1195
callback.key = 39457 jquery.js:1196
In callback[39457] ---- list.length to 1 jquery.js:1030
list.push = jquery.js:1031
function () {
// state = [ resolved | rejected ]
state = stateString;
// [ reject_list | resolve_list ].disable; progress_list.lock
} jquery.js:1032
In callback[39457] ---- list.length to 2 jquery.js:1030
list.push = jquery.js:1031
function () {
list = stack = memory = undefined;
return this;
} jquery.js:1032
In callback[39457] ---- list.length to 3 jquery.js:1030
list.push = jquery.js:1031
function () {
stack = undefined;
if ( !memory ) {
self.disable();
}
return this;
} jquery.js:1032
deferred.key = 55257 -> tuple[1] = progress jquery.js:1195
callback.key = 78608 jquery.js:1196
In callback[81354] ---- list.length to 8 jquery.js:1030
list.push = jquery.js:1031
function () {
var returned = fn.apply( this, arguments );
if ( returned && jQuery.isFunction( returned.promise ) ) {
returned.promise()
.done( newDefer.resolve )
.fail( newDefer.reject )
.progress( newDefer.notify );
} else {
// newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, [ returned ] ); }
} jquery.js:1032
In callback[4458] ---- list.length to 4 jquery.js:1030
list.push = jquery.js:1031
function () {
deferred[ tuple[0] + "With" ]( promise, arguments );
return this;
} jquery.js:1032
In callback[67133] ---- list.length to 1 jquery.js:1030
list.push = jquery.js:1031
function () {
deferred[ tuple[0] + "With" ]( promise, arguments );
return this;
} jquery.js:1032
In callback[24912] ---- list.length to 4 jquery.js:1030
list.push = jquery.js:1031
function ( result ) {
console.log("result = " + result);
value3 = result;
} jquery.js:1032
deferred.key = 83451 -> tuple[1] = done jquery.js:1195
callback.key = 13998 jquery.js:1196
In callback[13998] ---- list.length to 1 jquery.js:1030
list.push = jquery.js:1031
function () {
// state = [ resolved | rejected ]
state = stateString;
// [ reject_list | resolve_list ].disable; progress_list.lock
} jquery.js:1032
In callback[13998] ---- list.length to 2 jquery.js:1030
list.push = jquery.js:1031
function () {
list = stack = memory = undefined;
return this;
} jquery.js:1032
In callback[13998] ---- list.length to 3 jquery.js:1030
list.push = jquery.js:1031
function () {
stack = undefined;
if ( !memory ) {
self.disable();
}
return this;
} jquery.js:1032
deferred.key = 83451 -> tuple[1] = fail jquery.js:1195
callback.key = 94472 jquery.js:1196
In callback[94472] ---- list.length to 1 jquery.js:1030
list.push = jquery.js:1031
function () {
// state = [ resolved | rejected ]
state = stateString;
// [ reject_list | resolve_list ].disable; progress_list.lock
} jquery.js:1032
In callback[94472] ---- list.length to 2 jquery.js:1030
list.push = jquery.js:1031
function () {
list = stack = memory = undefined;
return this;
} jquery.js:1032
In callback[94472] ---- list.length to 3 jquery.js:1030
list.push = jquery.js:1031
function () {
stack = undefined;
if ( !memory ) {
self.disable();
}
return this;
} jquery.js:1032
deferred.key = 83451 -> tuple[1] = progress jquery.js:1195
callback.key = 27374 jquery.js:1196
In callback[24912] ---- list.length to 5 jquery.js:1030
list.push = jquery.js:1031
function () {
var returned = fn.apply( this, arguments );
if ( returned && jQuery.isFunction( returned.promise ) ) {
returned.promise()
.done( newDefer.resolve )
.fail( newDefer.reject )
.progress( newDefer.notify );
} else {
// newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, [ returned ] ); }
} jquery.js:1032
In callback[39457] ---- list.length to 4 jquery.js:1030
list.push = jquery.js:1031
function () {
deferred[ tuple[0] + "With" ]( promise, arguments );
return this;
} jquery.js:1032
In callback[78608] ---- list.length to 1 jquery.js:1030
list.push = jquery.js:1031
function () {
deferred[ tuple[0] + "With" ]( promise, arguments );
return this;
} jquery.js:1032
In callback[13998] ---- list.length to 4 jquery.js:1030
list.push = jquery.js:1031
function ( result ) {
console.log("result = " + result);
value3 = result;
} jquery.js:1032
In callback[81354].fire ---- list.length = 8 jquery.js:995
data = [object Object],[object Arguments] jquery.js:996
list[0] = function () {
// state = [ resolved | rejected ]
state = stateString;
// [ reject_list | resolve_list ].disable; progress_list.lock
} jquery.js:998
list[1] = function () {
list = stack = memory = undefined;
return this;
} jquery.js:998
list[2] = function () {
stack = undefined;
if ( !memory ) {
self.disable();
}
return this;
} jquery.js:998
list[3] = function (){
// console.log("I am 1st done");
} jquery.js:998
list[4] = function (a,b){
value1 = a;
value2 = b;
} jquery.js:998
list[5] = function (a,b){
console.log("a = " + a);
console.log("b = " + b);
return a * b;
} jquery.js:998
a = 2 deferred.js:113
b = 3 deferred.js:114
list[6] = function ( result ) {
console.log("result = " + result);
value3 = result;
} jquery.js:998
result = 2 deferred.js:118
list[7] = function () {
var returned = fn.apply( this, arguments );
if ( returned && jQuery.isFunction( returned.promise ) ) {
returned.promise()
.done( newDefer.resolve )
.fail( newDefer.reject )
.progress( newDefer.notify );
} else {
// newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, [ returned ] ); }
} jquery.js:998
a = 2 deferred.js:122
b = 3 deferred.js:123
In callback[24912].fire ---- list.length = 5 jquery.js:995
data = [object Object],6 jquery.js:996
list[0] = function () {
// state = [ resolved | rejected ]
state = stateString;
// [ reject_list | resolve_list ].disable; progress_list.lock
} jquery.js:998
list[1] = function () {
list = stack = memory = undefined;
return this;
} jquery.js:998
list[2] = function () {
stack = undefined;
if ( !memory ) {
self.disable();
}
return this;
} jquery.js:998
list[3] = function ( result ) {
console.log("result = " + result);
value3 = result;
} jquery.js:998
result = 6 deferred.js:127
list[4] = function () {
var returned = fn.apply( this, arguments );
if ( returned && jQuery.isFunction( returned.promise ) ) {
returned.promise()
.done( newDefer.resolve )
.fail( newDefer.reject )
.progress( newDefer.notify );
} else {
// newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, [ returned ] ); }
} jquery.js:998
a = 6 deferred.js:131
b = undefined deferred.js:132
In callback[13998].fire ---- list.length = 4 jquery.js:995
data = [object Object],NaN jquery.js:996
list[0] = function () {
// state = [ resolved | rejected ]
state = stateString;
// [ reject_list | resolve_list ].disable; progress_list.lock
} jquery.js:998
list[1] = function () {
list = stack = memory = undefined;
return this;
} jquery.js:998
list[2] = function () {
stack = undefined;
if ( !memory ) {
self.disable();
}
return this;
} jquery.js:998
list[3] = function ( result ) {
console.log("result = " + result);
value3 = result;
} jquery.js:998
result = NaN
end &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
下面这个testcase比较。。。
test( "jQuery.Deferred.then - deferred (done)", function() {
expect( 3 );
var value1, value2, value3,
defer = jQuery.Deferred(),
piped = defer.then(function( a, b ) {
return jQuery.Deferred(function( newDefer ) {
newDefer.reject( a * b );
});
});
piped.fail(function( result ) {
value3 = result;
});
piped.done(function( result ) { //not be executed
console.log("I am piped.done....................................................");
});
defer.done(function( a, b ) {
value1 = a;
value2 = b;
});
defer.resolve( 2, 3 );
strictEqual( value1, 2, "first resolve value ok" );
strictEqual( value2, 3, "second resolve value ok" );
strictEqual( value3, 6, "result of filter ok" );
});
defer.done.list:
[3] :從defer到piped
[4] :done(function( a, b )
piped.fail.list:
[3] : function( result ) {
value3 = result;
}
jQuery.Deferred.fail.list
[0] :returned.promise()
.done( newDefer.resolve )
.fail( newDefer.reject )
.progress( newDefer.notify );
執行順序:
1) defer.resolve( 2, 3 );
2) 執行到defer.done.list[3]時,then所帶function( a, b )觸發,
生成一個jQuery.Deferred,
這個jQuery.Deferred構造中,執行
function( newDefer ) { newDefer.reject( a * b );}
執行完jQuery.Deferred.fail.list
3) jQuery.Deferred 繼續執行
returned.promise()
.done( newDefer.resolve )
.fail( newDefer.reject )
.progress( newDefer.notify );
jQuery.Deferred.fail.list[0] 將fire
4) newDefer.reject 觸發piped.fail.list的執行
5) 最后執行defer.done.list[4]
參數傳遞過程,非常隱秘!
newDefer.reject( a * b );
jQuery.Deferred.fail.list執行時,
deferred[ tuple[0] + "With" ] = list.fireWith;
fireWith: function( context, args ) {
...
fire( args );
...
fire = function( data ) {
memory = options.memory && data;
result存到memory裡面,
然後通過
list[ firingIndex ].apply( data[ 0 ], data[ 1 ] )
deferred[ tuple[0] + "With" ]( promise, arguments );
傳出來。
var value1, value2, value3,
defer = jQuery.Deferred();
defer
.done(function(){
// console.log("I am 1st done");
})
.done(function(a,b){
value1 = a;
value2 = b;
})
.done(function(a,b){
log("a = " + a);
log("b = " + b);
return a * b;
})
.done(function( result ) {
log("result = " + result);
value3 = result;
})
.then(function( a, b ) {
log("a = " + a);
log("b = " + b);
return a * b;
})
.done(function( result ) {
log("result = " + result);
value3 = result;
})
.then(function( a, b ) {
log("a = " + a);
log("b = " + b);
return a * b;
})
.done(function( result ) {
log("result = " + result);
value3 = result;
})
;
defer.resolve( 2, 3 );
上面這段代碼的輸出是:
a = 2
b = 3
result = 2
a = 2
b = 3
result = 6
a = 6
b = undefined
result = NaN
參見:http://jsfiddle.net/JqRc9/
then()和done().fail().process()的差別是
then: function( /* fnDone, fnFail, fnProgress */ )會生成一個新的deferred,return jQuery.Deferred(function( newDefer )。初始化這個新deferred時,執行function( newDefer ),這個function添加一個callback func到前一個deferred。這個callback func是從老deferred到新deferred的橋樑,從deferred[ tuple[1]]到newDefer[ tuple[0] + "With" ]。對於每個deferred[ tuple[1] ],如果有對應的then()所帶function( /* fnDone, fnFail, fnProgress 之一*/ ),這個函數就是
function () {
var returned = fn.apply( this, arguments );
if ( returned && jQuery.isFunction( returned.promise ) ) {
returned.promise()
.done( newDefer.resolve )
.fail( newDefer.reject )
.progress( newDefer.notify );
} else {
newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, [ returned ] );
}
}
then所帶函數會被執行,返回returned,如果jQuery.isFunction( returned.promise ),则调用这个returned.promise的done、fail和progress,它们会对应触发newDefer的resolve、reject、notify; 否则 returned 傳入新的deferred,newDefer执行action + “with”;
如果沒有對應的then()所帶函數,簡單執行newDefer[ action ]。
上面的第一個result是第一個result的最后一個done()的輸出,前一個done的return不會傳遞到這裡,所以result是resolve的第一個參數。
第二個result是第二個deferred的輸出,第一個then所帶的function的輸入,傳入第二個deferred,因此第五個done能夠接受到2*3的result。
第三個result是第三個deferred的輸出,第二個then執行時,只有a,沒有b,所以result是NaN。
更多的log如下:
start deferred.js:100
************************************************ deferred.js:101
deferred.key = 29814 -> tuple[1] = done jquery.js:1195
callback.key = 81354 jquery.js:1196
In callback[81354] ---- list.length to 1 jquery.js:1030
list.push = jquery.js:1031
function () {
// state = [ resolved | rejected ]
state = stateString;
// [ reject_list | resolve_list ].disable; progress_list.lock
} jquery.js:1032
In callback[81354] ---- list.length to 2 jquery.js:1030
list.push = jquery.js:1031
function () {
list = stack = memory = undefined;
return this;
} jquery.js:1032
In callback[81354] ---- list.length to 3 jquery.js:1030
list.push = jquery.js:1031
function () {
stack = undefined;
if ( !memory ) {
self.disable();
}
return this;
} jquery.js:1032
deferred.key = 29814 -> tuple[1] = fail jquery.js:1195
callback.key = 4458 jquery.js:1196
In callback[4458] ---- list.length to 1 jquery.js:1030
list.push = jquery.js:1031
function () {
// state = [ resolved | rejected ]
state = stateString;
// [ reject_list | resolve_list ].disable; progress_list.lock
} jquery.js:1032
In callback[4458] ---- list.length to 2 jquery.js:1030
list.push = jquery.js:1031
function () {
list = stack = memory = undefined;
return this;
} jquery.js:1032
In callback[4458] ---- list.length to 3 jquery.js:1030
list.push = jquery.js:1031
function () {
stack = undefined;
if ( !memory ) {
self.disable();
}
return this;
} jquery.js:1032
deferred.key = 29814 -> tuple[1] = progress jquery.js:1195
callback.key = 67133 jquery.js:1196
In callback[81354] ---- list.length to 4 jquery.js:1030
list.push = jquery.js:1031
function (){
// console.log("I am 1st done");
} jquery.js:1032
In callback[81354] ---- list.length to 5 jquery.js:1030
list.push = jquery.js:1031
function (a,b){
value1 = a;
value2 = b;
} jquery.js:1032
In callback[81354] ---- list.length to 6 jquery.js:1030
list.push = jquery.js:1031
function (a,b){
console.log("a = " + a);
console.log("b = " + b);
return a * b;
} jquery.js:1032
In callback[81354] ---- list.length to 7 jquery.js:1030
list.push = jquery.js:1031
function ( result ) {
console.log("result = " + result);
value3 = result;
} jquery.js:1032
deferred.key = 55257 -> tuple[1] = done jquery.js:1195
callback.key = 24912 jquery.js:1196
In callback[24912] ---- list.length to 1 jquery.js:1030
list.push = jquery.js:1031
function () {
// state = [ resolved | rejected ]
state = stateString;
// [ reject_list | resolve_list ].disable; progress_list.lock
} jquery.js:1032
In callback[24912] ---- list.length to 2 jquery.js:1030
list.push = jquery.js:1031
function () {
list = stack = memory = undefined;
return this;
} jquery.js:1032
In callback[24912] ---- list.length to 3 jquery.js:1030
list.push = jquery.js:1031
function () {
stack = undefined;
if ( !memory ) {
self.disable();
}
return this;
} jquery.js:1032
deferred.key = 55257 -> tuple[1] = fail jquery.js:1195
callback.key = 39457 jquery.js:1196
In callback[39457] ---- list.length to 1 jquery.js:1030
list.push = jquery.js:1031
function () {
// state = [ resolved | rejected ]
state = stateString;
// [ reject_list | resolve_list ].disable; progress_list.lock
} jquery.js:1032
In callback[39457] ---- list.length to 2 jquery.js:1030
list.push = jquery.js:1031
function () {
list = stack = memory = undefined;
return this;
} jquery.js:1032
In callback[39457] ---- list.length to 3 jquery.js:1030
list.push = jquery.js:1031
function () {
stack = undefined;
if ( !memory ) {
self.disable();
}
return this;
} jquery.js:1032
deferred.key = 55257 -> tuple[1] = progress jquery.js:1195
callback.key = 78608 jquery.js:1196
In callback[81354] ---- list.length to 8 jquery.js:1030
list.push = jquery.js:1031
function () {
var returned = fn.apply( this, arguments );
if ( returned && jQuery.isFunction( returned.promise ) ) {
returned.promise()
.done( newDefer.resolve )
.fail( newDefer.reject )
.progress( newDefer.notify );
} else {
// newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, [ returned ] ); }
} jquery.js:1032
In callback[4458] ---- list.length to 4 jquery.js:1030
list.push = jquery.js:1031
function () {
deferred[ tuple[0] + "With" ]( promise, arguments );
return this;
} jquery.js:1032
In callback[67133] ---- list.length to 1 jquery.js:1030
list.push = jquery.js:1031
function () {
deferred[ tuple[0] + "With" ]( promise, arguments );
return this;
} jquery.js:1032
In callback[24912] ---- list.length to 4 jquery.js:1030
list.push = jquery.js:1031
function ( result ) {
console.log("result = " + result);
value3 = result;
} jquery.js:1032
deferred.key = 83451 -> tuple[1] = done jquery.js:1195
callback.key = 13998 jquery.js:1196
In callback[13998] ---- list.length to 1 jquery.js:1030
list.push = jquery.js:1031
function () {
// state = [ resolved | rejected ]
state = stateString;
// [ reject_list | resolve_list ].disable; progress_list.lock
} jquery.js:1032
In callback[13998] ---- list.length to 2 jquery.js:1030
list.push = jquery.js:1031
function () {
list = stack = memory = undefined;
return this;
} jquery.js:1032
In callback[13998] ---- list.length to 3 jquery.js:1030
list.push = jquery.js:1031
function () {
stack = undefined;
if ( !memory ) {
self.disable();
}
return this;
} jquery.js:1032
deferred.key = 83451 -> tuple[1] = fail jquery.js:1195
callback.key = 94472 jquery.js:1196
In callback[94472] ---- list.length to 1 jquery.js:1030
list.push = jquery.js:1031
function () {
// state = [ resolved | rejected ]
state = stateString;
// [ reject_list | resolve_list ].disable; progress_list.lock
} jquery.js:1032
In callback[94472] ---- list.length to 2 jquery.js:1030
list.push = jquery.js:1031
function () {
list = stack = memory = undefined;
return this;
} jquery.js:1032
In callback[94472] ---- list.length to 3 jquery.js:1030
list.push = jquery.js:1031
function () {
stack = undefined;
if ( !memory ) {
self.disable();
}
return this;
} jquery.js:1032
deferred.key = 83451 -> tuple[1] = progress jquery.js:1195
callback.key = 27374 jquery.js:1196
In callback[24912] ---- list.length to 5 jquery.js:1030
list.push = jquery.js:1031
function () {
var returned = fn.apply( this, arguments );
if ( returned && jQuery.isFunction( returned.promise ) ) {
returned.promise()
.done( newDefer.resolve )
.fail( newDefer.reject )
.progress( newDefer.notify );
} else {
// newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, [ returned ] ); }
} jquery.js:1032
In callback[39457] ---- list.length to 4 jquery.js:1030
list.push = jquery.js:1031
function () {
deferred[ tuple[0] + "With" ]( promise, arguments );
return this;
} jquery.js:1032
In callback[78608] ---- list.length to 1 jquery.js:1030
list.push = jquery.js:1031
function () {
deferred[ tuple[0] + "With" ]( promise, arguments );
return this;
} jquery.js:1032
In callback[13998] ---- list.length to 4 jquery.js:1030
list.push = jquery.js:1031
function ( result ) {
console.log("result = " + result);
value3 = result;
} jquery.js:1032
In callback[81354].fire ---- list.length = 8 jquery.js:995
data = [object Object],[object Arguments] jquery.js:996
list[0] = function () {
// state = [ resolved | rejected ]
state = stateString;
// [ reject_list | resolve_list ].disable; progress_list.lock
} jquery.js:998
list[1] = function () {
list = stack = memory = undefined;
return this;
} jquery.js:998
list[2] = function () {
stack = undefined;
if ( !memory ) {
self.disable();
}
return this;
} jquery.js:998
list[3] = function (){
// console.log("I am 1st done");
} jquery.js:998
list[4] = function (a,b){
value1 = a;
value2 = b;
} jquery.js:998
list[5] = function (a,b){
console.log("a = " + a);
console.log("b = " + b);
return a * b;
} jquery.js:998
a = 2 deferred.js:113
b = 3 deferred.js:114
list[6] = function ( result ) {
console.log("result = " + result);
value3 = result;
} jquery.js:998
result = 2 deferred.js:118
list[7] = function () {
var returned = fn.apply( this, arguments );
if ( returned && jQuery.isFunction( returned.promise ) ) {
returned.promise()
.done( newDefer.resolve )
.fail( newDefer.reject )
.progress( newDefer.notify );
} else {
// newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, [ returned ] ); }
} jquery.js:998
a = 2 deferred.js:122
b = 3 deferred.js:123
In callback[24912].fire ---- list.length = 5 jquery.js:995
data = [object Object],6 jquery.js:996
list[0] = function () {
// state = [ resolved | rejected ]
state = stateString;
// [ reject_list | resolve_list ].disable; progress_list.lock
} jquery.js:998
list[1] = function () {
list = stack = memory = undefined;
return this;
} jquery.js:998
list[2] = function () {
stack = undefined;
if ( !memory ) {
self.disable();
}
return this;
} jquery.js:998
list[3] = function ( result ) {
console.log("result = " + result);
value3 = result;
} jquery.js:998
result = 6 deferred.js:127
list[4] = function () {
var returned = fn.apply( this, arguments );
if ( returned && jQuery.isFunction( returned.promise ) ) {
returned.promise()
.done( newDefer.resolve )
.fail( newDefer.reject )
.progress( newDefer.notify );
} else {
// newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, [ returned ] ); }
} jquery.js:998
a = 6 deferred.js:131
b = undefined deferred.js:132
In callback[13998].fire ---- list.length = 4 jquery.js:995
data = [object Object],NaN jquery.js:996
list[0] = function () {
// state = [ resolved | rejected ]
state = stateString;
// [ reject_list | resolve_list ].disable; progress_list.lock
} jquery.js:998
list[1] = function () {
list = stack = memory = undefined;
return this;
} jquery.js:998
list[2] = function () {
stack = undefined;
if ( !memory ) {
self.disable();
}
return this;
} jquery.js:998
list[3] = function ( result ) {
console.log("result = " + result);
value3 = result;
} jquery.js:998
result = NaN
end &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
下面这个testcase比较。。。
test( "jQuery.Deferred.then - deferred (done)", function() {
expect( 3 );
var value1, value2, value3,
defer = jQuery.Deferred(),
piped = defer.then(function( a, b ) {
return jQuery.Deferred(function( newDefer ) {
newDefer.reject( a * b );
});
});
piped.fail(function( result ) {
value3 = result;
});
piped.done(function( result ) { //not be executed
console.log("I am piped.done....................................................");
});
defer.done(function( a, b ) {
value1 = a;
value2 = b;
});
defer.resolve( 2, 3 );
strictEqual( value1, 2, "first resolve value ok" );
strictEqual( value2, 3, "second resolve value ok" );
strictEqual( value3, 6, "result of filter ok" );
});
defer.done.list:
[3] :從defer到piped
[4] :done(function( a, b )
piped.fail.list:
[3] : function( result ) {
value3 = result;
}
jQuery.Deferred.fail.list
[0] :returned.promise()
.done( newDefer.resolve )
.fail( newDefer.reject )
.progress( newDefer.notify );
執行順序:
1) defer.resolve( 2, 3 );
2) 執行到defer.done.list[3]時,then所帶function( a, b )觸發,
生成一個jQuery.Deferred,
這個jQuery.Deferred構造中,執行
function( newDefer ) { newDefer.reject( a * b );}
執行完jQuery.Deferred.fail.list
3) jQuery.Deferred 繼續執行
returned.promise()
.done( newDefer.resolve )
.fail( newDefer.reject )
.progress( newDefer.notify );
jQuery.Deferred.fail.list[0] 將fire
4) newDefer.reject 觸發piped.fail.list的執行
5) 最后執行defer.done.list[4]
參數傳遞過程,非常隱秘!
newDefer.reject( a * b );
jQuery.Deferred.fail.list執行時,
deferred[ tuple[0] + "With" ] = list.fireWith;
fireWith: function( context, args ) {
...
fire( args );
...
fire = function( data ) {
memory = options.memory && data;
result存到memory裡面,
然後通過
list[ firingIndex ].apply( data[ 0 ], data[ 1 ] )
deferred[ tuple[0] + "With" ]( promise, arguments );
傳出來。
相关推荐
.done(…) .fail(…) .progress(…) .always(…) Multiple promises .when(p1, p2, p3, …).then(…) Callable and Runnable wrappers .when(new Runnable() {…}) Uses Executor Service Java Generics ...
Promise 对象可以看作是 Deferred 对象的一个只读视图,因为它包含了 Deferred 对象的一系列方法,如 `done()`, `then()`, `fail()`, `isResolved()`, `isRejected()`, `always()`。这些方法允许外部代码监听 ...
7. **deferred.then()**:简化done()和fail(),可以同时指定成功和失败的回调。若只有一个参数,则相当于done()。 8. **deferred.always()**:无论deferred对象是成功还是失败,都会执行的回调函数。 #### 使用示例...
6. **fail()**:当Deferred对象被reject时执行的回调函数。 7. **progress()**:当Deferred对象被notify时执行的回调函数。 #### 三、jQuery.Deferred源码剖析 1. **数组tuples**:定义了Deferred对象的三种状态...
8. `deferred.then([doneCallbacks], [failCallbacks], [progressCallbacks])`:这是一个组合方法,可以同时指定成功、失败和进度的回调。 `deferred.pipe()` 方法允许对结果进行过滤和转换。例如,我们可以创建一...
在jQuery中,`$.Deferred()`创建了一个可以监视和控制异步操作的对象,它支持多种状态(pending、resolved、rejected),并且可以通过`.then()`、`.done()`、`.fail()`、`.always()`等方法来注册成功、失败或无论...
`deferred.then()`方法相比于`deferred.done()`和`deferred.fail()`提供了更多的灵活性和控制力。`then()`方法不仅能够接收成功和失败的回调,还能接收一个处理中的回调,并且能够返回一个新的promise对象。这是...
3. `promise()`: 这个方法返回一个新的Promise对象,可以用于链式调用`.then()`, `.done()`, `.fail()`, 和其他Promise方法,而不会影响原始的Deferred对象。 在JavaScript的Promise规范中,虽然没有直接的 ...
4. `.then()`:这是一个组合方法,可以同时处理成功和失败的回调,类似于`.done()`和`.fail()`的组合。 5. `.progress()`:用于在异步操作过程中传递进度信息。 三、使用deferred对象处理Ajax请求 在jQuery 1.5及...
在这里,$.ajax的Promise通过done()和fail()方法连接到了deferred,使得deferred可以控制最终的决议状态。此外,Deferred对象还提供了resolve()和reject()方法,以及notify()方法来传递进度信息。这些方法可以接收...
Promise对象提供了`.then()`、`.done()`、`.fail()`等方法来处理异步操作的结果。 2. Deferred对象:jQuery中的Deferred对象比Promise更加强大,因为它可以控制异步操作的状态,并且提供了`.resolve()`和`.reject()...
此外,`.then()`方法也可以用来替代`.done()`和`.fail()`,它可以接受两个参数,分别对应成功和失败的回调。 ### 为多个`ajax`请求指定回调函数 当你需要为多个异步操作设置统一的回调时,可以使用`$.when()`方法...
var methods = 'done,resolveWith,resolve,isResolved,then,fail,rejectWith,reject,isRejected,promise'.split(','), method, ajaxMethods = [], onlyInDeferredMethods = []; for (method in $.ajax()) { if ...
除了`.done()`, `.fail()`, `.always()`和`.then()`,Promise还提供了`.catch()`和`.finally()`方法,它们分别对应于`.fail()`和`.always()`,使得错误处理更加直观。 - `.catch()`:捕获并处理Promise链中的错误,...
jQuery的`$.ajax()`函数默认返回一个`deferred`对象,这意味着你可以直接在`.ajax()`调用后链式调用`.done()`, `.fail()`, 或 `.then()`等方法。例如: ```javascript $.ajax('test.json') .done(function(resp) {...
例如,你可以添加多个`done`、`fail`和`always`回调,这些回调会在适当的时间点被触发。此外,`$.when`可以用于处理多个异步操作,当所有操作都完成时,它会触发一个回调。 除了在AJAX请求中使用,`deferred`对象也...