6

この jsFiddleに関して、イベントがトリガーされたときに作成される「遅延」を動的に追加しようとしているため、後で追加されたものを含め、すべての遅延が解決されたときにのみ完了コールバックが呼び出されます。

関連コード:

var promises = [ deferred1, ... ];
var p = when.all(promises).then(function() {
  console.log('All done!!');
  //! trigger
});

promises.push( deferredFromEvent ); // << ignored

更新: Q または jQuery を使用した提案を歓迎します。動作するものを探しています

4

4 に答える 4

0

「...だから、完了したコールバックは、後で追加されたものを含め、すべての遅延が解決されたときにのみ呼び出されます」は意味がありませんが、私はあなたが何を意味するか知っていると思います.

私が正しく理解していれば、「re-firable when()」と呼ばれるものが必要です-次のようなもの(jQueryに基づく):

function PromiseSet(memory, once) {//javascript Constructor
    var flags = [];
    if(memory) flags.push('memory');
    if(once) flags.push('once');
    var promises = [],
        doneCallbacks = $.Callbacks(flags.join(' ')),
        failCallbacks = $.Callbacks(flags.join(' '));
    this.add = function(promise, val) {
        promises.push(promise);
        if(val) { this.fire(val); }
        return this;
    };
    this.done = function(fn) {
        doneCallbacks.add(fn);
        return this;
    };
    this.fail = function(fn) {
        failCallbacks.add(fn);
        return this;
    };
    this.fire = function(val) {
        val = val || null;
        $.when.apply($, promises).then(
            function() { doneCallbacks.fire(val); },
            function() { failCallbacks.fire(val); }
        );
        return this;
    };
    return this;
}

テストされていない

すべてのメソッドはこれを返し、連鎖可能にします。

コンストラクターを正しく記述した場合は、ブール値を に渡すことで、その詳細な動作を制御できますnew PromiseSet()。提案された使用法では、渡す必要があると思いますが(true, false)、他の設定を試して何が起こるかを確認してください。

サンプルシーケンス:

var myPromiseSet = new PromiseSet(true, false);
myPromiseSet.add(promise1);
myPromiseSet.add(promise2).add(promise3);
myPromiseSet.done(myDoneFunction).fail(myFailFunction);
myPromiseSet.fire("foo");
myPromiseSet.add(promise4).fire();
于 2013-02-20T04:45:38.927 に答える
0

前もって必要であることがわかっているすべての約束を作成します。それらを使用して構築.whenします。から返された promise を保存します.when。新しい promiseを必要とする新しいイベントを追加するときは.when、前.whenの からの promise と、完了した新しい promise を使用して、新しい を追加します。

「アプリを進めてください」としてsingle points of failureファイナルを使用している場合、アプリケーションには複数の があります。.whenIE: いずれかの promise が失敗した場合、その後に.when作成されたものも失敗します。

...しかし、それがあなたの意図である場合、または確かなエラー処理がある場合は、それで十分です。

私はこのライブラリにとらわれないようにしようとしています -- 通常、私は独自の実装を使用します。これは、jQuery が行うことと、Crockford が最近の講演で行ったことの中間ですが、次のように仮定すると、

関数
は promise-handler を返す "when" が promise-handler を返す promise-handlers には少なくとも.doneand.failがあり、または 2 つの引数を受け入れるか、関数内で何が起こるかによって、promise がrejected/resolvedor kept/broken(または何でも) であるかどうかが制御されます。次のような一連の機能が得られる場合があります。

var doing = doSomething(),     // returns promise
    making = makeSomething(),  // returns promise
    loading = loadSomething(), // returns promise


    dependencies_lvl_1 = when(doing, making, loading);

後で、新しいモジュールやウィジェットを追加するかもしれません -- 多分それはいくらかの手間を省きます:

var saving = saveSomething(), //returns promise
    dependencies_lvl_2 = when(dependencies_lvl_1, saving);

その後、ページを切り替える必要があるかもしれませんが、最初にデータをキャッシュする必要があります

var caching = cacheData(),   // returns promise
    when(dependencies_lvl_2, caching)
        .done(goToNextPage)
        .fail(handleError);

それを見ると、すべての約束が守られている場合 (およびすべての約束が守られている場合) にのみ成功する約束を返す限り、それらのどれも壊れていないことがわかりますwhen。追加のお約束。dependencies_lvl_2dependencies_lvl_1

レベル 3.whenには、チェーンに追加されたすべてのものに応じた解決策があります。

そして、Promise を変数 (またはある種の将来アクセス) にキャッシュし続ける限り、これらを連鎖させ続けることができます。

于 2013-02-19T17:59:02.210 に答える
0

この解決策を見てください。この実装により、多くの動的に追加されたプロミスを追跡できます。jQuery Deferred を使用している場合は、この方法で実行できます。 jsフィドル

lodash ライブラリの_.everyメソッドを使用したので、lodash もインストールする必要があります。

function doAlotOfAsyncThings(callback) {
    var promises = [];
    var def = $.Deferred();
    console.log('Adding first promise');
    promises.push(def.promise());

    setTimeout(function() {
        // Dinamically adding second promise. Important note: last added promise must be added to array BEFORE previous promise has been resolved
        var def2 = $.Deferred();
        var def3 = $.Deferred();
        console.log('Dinamically adding second and third promises');
        promises.push(def2.promise());
        promises.push(def3.promise());
        console.log('Resolving first promise');
        def.resolve();

        setTimeout(function() {
            console.log('Resolving second and third promises');
            def2.resolve();
            def3.resolve();
        }, 1500);
    }, 1000);


    function checkAllDone() {
        console.log('Checking $.when');
        $.when.apply(null, promises).then(function() {
            // we have to check state of every promise in array
            var all_resolved = _.every(promises, function(elem) { return elem.state() == 'resolved'; });
            if(all_resolved) {
                console.log('All promises are resolved! callback();')
                callback();
            } else {
                console.log('Hm, seems that some promises were dinamically added, waiting for them..');
                checkAllDone();
            }
        });
    }
    checkAllDone();
}

doAlotOfAsyncThings(function(){
    console.log('Done');
});

Q.js を使用すると、さらに短くなります。
このソリューションでは、lodash ライブラリの_.anyメソッドを使用します

function doAlotOfAsyncThings(callback) {
    var promises = [];
    var def = Q.defer();
    console.log('Adding first promise');
    promises.push(def.promise);

    setTimeout(function() {
        // Dinamically adding second promise. Important note: last added promise must be added to array BEFORE previous promise has been resolved
        var def2 = Q.defer();
        var def3 = Q.defer();
        console.log('Dinamically adding second and third promises');
        promises.push(def2.promise);
        promises.push(def3.promise);
        console.log('Resolving first promise');
        def.resolve();

        setTimeout(function() {
            console.log('Resolving second and third promises');
            def2.resolve();
            def3.resolve();
        }, 1500);
    }, 1000);


    function checkAllDone() {
        console.log('Checking $.when');
        Q.all(promises).then(function() {
            // Q remove resolved promises from array so we have to check if array contains some non-undefined elements (those elements would be non-resolved dinamically added promises)
            if(_.any(promises)) {
                console.log('Hm, seems that some promises were dinamically added, waiting for them..');
                checkAllDone();
            } else {
                console.log('All promises are resolved! callback();')
                callback();
            }
        });
    }
    checkAllDone();
}

doAlotOfAsyncThings(function(){
    console.log('Done');
});
于 2014-12-23T09:32:49.017 に答える