編集:最初の質問を忘れました。 この動作は、closure( "x"関数のdfd変数)の手段によって実現されます。
実行チェーンのすべてのDeferredsが作成され、 "executePromiseQueueSync"のdone、fail、progressのフックが実行されたため、関数 "x"がすぐに戻ります(通知イベントをトリガーして処理できるようになりました)。フック)。
また、setTimeoutの関数はクロージャのdfdを「閉じる」ので、「x」が返っても変数にアクセスできます。 "then"コールは、最初のものにリンクされている次の遅延を作成することによって継続されます。
JS VMが実行すると(それ以外の処理はない)、setTimeoutは関連する関数をトリガし、クロージャの手段によって「閉じた」dfd変数にアクセスします。 Deferredが解決され、チェーンは続行できます。
EDIT2:Here is a refactored version彼らは彼らの進歩のために自分の発信者に通知し、長い実行し、繰延サポートしている機能のサポートが追加されます。
EDIT3:ここではanother versionです。アンダースコアバインディングはなく、jq-uiプログレスバーの例もあります。
ところで、これは複雑なアプリの初期化ルーチンにとって非常に良いアイデアです。
(最初のバージョンの)ソース
function executePromiseQueueSync(queue, beacon){
var seed = $.Deferred(),
le = queue.length,
last;
beacon.notify(0);
last = _.reduce(queue, function(memo, ent, ind){
var df = $.Deferred();
df.then(function(){
console.log("DBG proggie");
beacon.notify((ind+1)/le*100);
});
console.log("DBG hook funk "+ind);
memo.then(function(){
console.log("DBG exec func "+ind);
ent.funct.apply(null, ent.argmnt);
df.resolve();
});
return df.promise();
}, seed.promise());
last.then(function(){
beacon.resolve(100)
});
seed.resolve(); // trigger
return beacon.promise();
}
function x(){
// do stuff
console.log("blah");
}
var promisesQueue = [],
beacon = $.Deferred();
promisesQueue.push({funct: x, argmnt:[]});
promisesQueue.push({funct: x, argmnt:[]});
promisesQueue.push({funct: x, argmnt:[]});
function monTheProg(pct)
{
console.log('progress '+pct);
}
// first hook, then exec
beacon.then(function(){
console.log('success');
}, function(){
console.log('failure');
}, monTheProg);
// do the dance
executePromiseQueueSync(promisesQueue, beacon)
ただ、最後の質問からいくつかの背景情報を追加するには、setTimeoutメソッドが必要とされる理由は、繰延オブジェクトがバインドされた多くのprogressイベントを持つことができません解決されます。解決を遅らせることによって、 '.then'は進捗イベントにバインドすることができます。 –
すべての微妙な結果が分かると、これは非常に厄介な動作です。 – mnowotka
私はそれほど理解していない部分があります。私たちが解決を遅らせると、このコールバックが戻る前に呼び出される.notifyをキャッチすることはどうですか?それについて考える。その後、最初のパラメータから返された遅延オブジェクトを取得し、そこから新しい遅延オブジェクトを作成し、進行状況および失敗イベントにバインドします。通知が遅延が返される前に呼び出された場合、setTimeoutを使用してもそれをキャッチするのはどうですか? –