`
xing_kenny
  • 浏览: 3418 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

deferred.then() 和 deferred.done().fail() 的不同

阅读更多
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 );
    傳出來。
分享到:
评论

相关推荐

    Android代码-jdeferred

    .done(…) .fail(…) .progress(…) .always(…) Multiple promises .when(p1, p2, p3, …).then(…) Callable and Runnable wrappers .when(new Runnable() {…}) Uses Executor Service Java Generics ...

    深入解析jQuery中Deferred的deferred.promise()方法

    Promise 对象可以看作是 Deferred 对象的一个只读视图,因为它包含了 Deferred 对象的一系列方法,如 `done()`, `then()`, `fail()`, `isResolved()`, `isRejected()`, `always()`。这些方法允许外部代码监听 ...

    jQuery中的deferred对象和extend方法详解

    7. **deferred.then()**:简化done()和fail(),可以同时指定成功和失败的回调。若只有一个参数,则相当于done()。 8. **deferred.always()**:无论deferred对象是成功还是失败,都会执行的回调函数。 #### 使用示例...

    谈谈jQuery之Deferred源码剖析

    6. **fail()**:当Deferred对象被reject时执行的回调函数。 7. **progress()**:当Deferred对象被notify时执行的回调函数。 #### 三、jQuery.Deferred源码剖析 1. **数组tuples**:定义了Deferred对象的三种状态...

    jquery Deferred 快速解决异步回调的问题

    8. `deferred.then([doneCallbacks], [failCallbacks], [progressCallbacks])`:这是一个组合方法,可以同时指定成功、失败和进度的回调。 `deferred.pipe()` 方法允许对结果进行过滤和转换。例如,我们可以创建一...

    android-deferred,.zip

    在jQuery中,`$.Deferred()`创建了一个可以监视和控制异步操作的对象,它支持多种状态(pending、resolved、rejected),并且可以通过`.then()`、`.done()`、`.fail()`、`.always()`等方法来注册成功、失败或无论...

    jQuery的deferred对象使用详解

    `deferred.then()`方法相比于`deferred.done()`和`deferred.fail()`提供了更多的灵活性和控制力。`then()`方法不仅能够接收成功和失败的回调,还能接收一个处理中的回调,并且能够返回一个新的promise对象。这是...

    Deferred

    3. `promise()`: 这个方法返回一个新的Promise对象,可以用于链式调用`.then()`, `.done()`, `.fail()`, 和其他Promise方法,而不会影响原始的Deferred对象。 在JavaScript的Promise规范中,虽然没有直接的 ...

    jQuery.deferred对象使用详解

    4. `.then()`:这是一个组合方法,可以同时处理成功和失败的回调,类似于`.done()`和`.fail()`的组合。 5. `.progress()`:用于在异步操作过程中传递进度信息。 三、使用deferred对象处理Ajax请求 在jQuery 1.5及...

    jQuery中的Deferred和promise 的区别

    在这里,$.ajax的Promise通过done()和fail()方法连接到了deferred,使得deferred可以控制最终的决议状态。此外,Deferred对象还提供了resolve()和reject()方法,以及notify()方法来传递进度信息。这些方法可以接收...

    jQuery的promise与deferred对象在异步回调中的作用

    Promise对象提供了`.then()`、`.done()`、`.fail()`等方法来处理异步操作的结果。 2. Deferred对象:jQuery中的Deferred对象比Promise更加强大,因为它可以控制异步操作的状态,并且提供了`.resolve()`和`.reject()...

    jQuery中的deferred使用方法

    此外,`.then()`方法也可以用来替代`.done()`和`.fail()`,它可以接受两个参数,分别对应成功和失败的回调。 ### 为多个`ajax`请求指定回调函数 当你需要为多个异步操作设置统一的回调时,可以使用`$.when()`方法...

    在jQuery1.5中使用deferred对象 着放大镜看Promise

    var methods = 'done,resolveWith,resolve,isResolved,then,fail,rejectWith,reject,isRejected,promise'.split(','), method, ajaxMethods = [], onlyInDeferredMethods = []; for (method in $.ajax()) { if ...

    以jQuery中$.Deferred对象为例讲解promise对象是如何处理异步问题

    除了`.done()`, `.fail()`, `.always()`和`.then()`,Promise还提供了`.catch()`和`.finally()`方法,它们分别对应于`.fail()`和`.always()`,使得错误处理更加直观。 - `.catch()`:捕获并处理Promise链中的错误,...

    详解jQuery中的deferred对象的使用(一)

    jQuery的`$.ajax()`函数默认返回一个`deferred`对象,这意味着你可以直接在`.ajax()`调用后链式调用`.done()`, `.fail()`, 或 `.then()`等方法。例如: ```javascript $.ajax('test.json') .done(function(resp) {...

    jQuery中借助deferred来请求及判断AJAX加载的实例讲解

    例如,你可以添加多个`done`、`fail`和`always`回调,这些回调会在适当的时间点被触发。此外,`$.when`可以用于处理多个异步操作,当所有操作都完成时,它会触发一个回调。 除了在AJAX请求中使用,`deferred`对象也...

Global site tag (gtag.js) - Google Analytics