3

単一の Deferred オブジェクトを作成すると、期待どおりに進行状況が報告されます。

var d1 = function() {
    var d = $.Deferred();
    d.notify('d1');
    d.resolve('d1');
    return d.promise();
};

d1().progress(function(a) {
    log('Progress: ' + a);
});

ただし、then() を使用して 2 つの Deferred オブジェクトをチェーンすると、進行状況のコールバックは呼び出されません。

d1().then(d1).progress(function(a) {
    log('Progress: ' + a);
});

then() は進行状況の通知を伝達する必要があるように思えますが、そうではないようです。何か不足していますか?

これを jQuery 1.8.0 および 1.8.1 でテストしました。完全な動作例はこちら: http://jsfiddle.net/eWQuG/13/

4

2 に答える 2

2

何が起こっているかはわかりますが、説明するのは少し難しいです。これを数回読む必要があるかもしれません...

テスト 1 では、渡される promisetest()は「元の promise」です。によって返されるオブジェクトd1()。単純。

テスト 2 では、 に渡されたオブジェクトは、 から生成されtest()新しいpromised1().then(d2).then(d3)です。単純ではありません。この新しい promise は、元の promise のプロパティの一部のみを継承します。progressCallbacks は含まれません (元の promise で導入されているようにnotify())。これは、によって返される promise にとって妥当です。 は、独自のdoneCallbacks、failCallbacks、progressCallbacksを配置するように設計されており、deferred/promise のものをすぐ左に伝播しないように設計されて.then()いるためです。要するに、その名前が意味することを正確に行います -前の deferred/promise が処理された後に何をすべきかを指定します。.then().then()

元の promise (つまり の出力) への参照を保持することで、何が起こっているのかをよりよく理解d1()できるため、単純なテスト 1 をテスト 2 の前後の両方で実行できます。

複合テスト 3 は次のとおりです。

log('-- Test 3 --');
var p = d1();//p is a promise
test(p);//equivalent to Test 1
test(p.then(d2).then(d3));//equivalent to Test 2
test(p);//equivalent to Test 1 again

デモ

ログを見るとtest(p)、どちらの場合も の動作が同じであることがわかります。ただし、test(p.then(d2).then(d3))渡されたオブジェクトは元の promise ではなく、progressCallbacks のない新しい promise であるため、動作が異なります。

編集

ライアン、あなたが望むものを達成するために検討する価値があるかもしれません:

d1().then(d2).progress(function(a) {
    log('Progress: ' + a);
});

つまり、チェーンは次のように再配置できます。

d1().progress(function(a) {
    log('Progress: ' + a);
}).then(d2);

したがって、プログレス コールバックは元の promise に適用され、元の promise を.progress()チェーンに伝播するため.then()、以前と同様に動作します。

どちらのバージョンも有効ですが、異なる状況に適用できます。

私が正しければ、これがあなたの質問に対する短い答えかもしれません。

于 2012-09-21T01:46:36.870 に答える