1

私のコードが示すように、私は現在、2 つの非同期コールバック関数 (success と callback) に promise を渡しています。これを別の方法で行うことは可能だと思いますが、他に方法はまだ見つかりません。

プロミスを作成し、それらがすべて完了するのを待つ私の関数は次のとおりです。

_onModelLoaded: function(model) {
    var promises = [];

    _.each(this._customRecords, function(defect, index) {
        promises.push(this._getHistory(model, defect));
    }, this);

    Deft.Promise.all(promises).then({
        success: function(something) {
            console.log('woot',something);
        }
    });
},

この_getHistory関数は promise を作成し、それを 2 つの関数 (_onHistoryLoaded と _onRevisionsLoaded) に渡します。これにより、これらのコールバックが実行されると、promise が解決されます。

_getHistory: function(model,defect) {
    var deferred = Ext.create('Deft.promise.Deferred');

    model.load(Rally.util.Ref.getOidFromRef(defect.RevisionHistory), {
        scope: this,
        success: function(record) {
            this._onHistoryLoaded(defect, record, deferred);
        }
    });

    return deferred.promise;
},

_onHistoryLoaded: function(defect, record, def) {
    record.getCollection('Revisions').load({
        fetch: ['RevisionNumber', 'CreationDate', 'User', 'Description'],
        scope: this,
        callback: function(revisions) {
            this._onRevisionsLoaded(revisions, defect, def);
        }
    });
},

_onRevisionsLoaded: function(revisions, defect, def) {

    _.each(revisions, function(revision, revisionIndex) {
        // Do stuff with each revision
    }, this);

    def.resolve(defect);
},

最終的な欠陥をプロミスに渡す必要は必ずしもありません。テストのために解決ステートメントに入れるだけです。

注:私のコードは正しく実行されます。簡略化を求めているだけです。

それを解決するためにいくつかの非同期関数を通過させるためだけにプロミスを作成しないようにする方法はありますか?

4

2 に答える 2

2

役立つヒントをいくつか紹介しようと思いますが、最初にいくつかの注意事項があります。

  1. あなたが解決しようとしているドメインの問題については何も知りません。そのため、物事に最適な名前を​​決定したり、機能の各ユニットが物事の壮大な計画のどこに適合するかを正確に決定したりすることが難しくなっています。

  2. お使いのライブラリは、Promises/A+ および次のバージョンの JavaScript で使用される Promise API をサポートしていないようです。真のプロミスの仕様は、http: //promisesaplus.com/で読むことができます。私は、http://www.promisejs.org/implementations/で私のお気に入りの実装の短いリストを維持しています。

これらの実装の最初であり、私が自分で書いた「Promise」で書くように、コードを書いてみます。

onHistoryLoaded は実際には非同期操作であるため、その名前を実行するアクションに変更し、promise を返すようにします。同じことをして、 1 つのジョブだけを実行しますonRevisionsLoadedgetHistory

_onModelLoaded: function(model) {
    var promises = _.map(this._customRecords, function(defect, index) {
        this._getHistoryRevisions(model, defect).then(function (revisions) {
            _.each(revisions, function (revision, revisionIndex) {
              // Do stuff wich each revision
            }, this);
        }.bind(this));
    }, this);

    Promise.all(promises).done(function(something) {
        console.log('woot',something);
    });
},

_getHistoryRevisions: function (model, defect) {
    return this._getHistory(model, defect).then(function (record) {
        return this._getRevisions(record);
    }.bind(this));
},

_getHistory: function(model, defect) {
    return new Promise(function (resolve, reject) {
        model.load(Rally.util.Ref.getOidFromRef(defect.RevisionHistory), {
            scope: this,
            success: function(record) {
                resolve(record);
            }
        });
    }.bind(this));
},

_getRevisions: function(record) {
    return new Promise(function (resolve, reject) {
        record.getCollection('Revisions').load({
            fetch: ['RevisionNumber', 'CreationDate', 'User', 'Description'],
            scope: this,
            callback: function(revisions) {
                resolve(revisions);
            }
        });
    }.bind(this));
}

可能な限り、何が原因ではなく、機能にちなんで関数に名前を付けるのが最善です。それらは、それらの前後に起こることと結びつける必要はありません。プロミスの背後にある考え方の大部分は、関数を呼び出して何かを実行してから値を返すというプログラミングの同期モデルに簡単に戻れるようにするというものです。関数がどこで使用されるかを認識していないほど、他の場所で再利用するのが簡単になります:)

于 2013-12-25T00:07:04.033 に答える
0

@ForbesLindesay から提供された回答は非常に役に立ちました。ただし、私は Deft 0.8.0 を使用していたため、これらの promise の実装にはいくつかの違いがありました。チェーンを機能させる方法は次のとおりです。

_onModelLoaded: function(model) {
    var promises = [];

    _.each(this._customRecords, function(defect, index) {
        promises.push(this._getHistoryRevisions(model, defect).then(function (revisions) {
            // do stuff with revisions
        }.bind(this)));
    }, this);

    Deft.Promise.all(promises).then(function(something) {
        console.log('woot',something);
    }.bind(this));
},

_getHistoryRevisions: function (model, defect) {
    return this._getHistory(model, defect).then(function (record) {
        return this._getRevisions(record);
    }.bind(this));
},

_getHistory: function (model, defect) {
    var deferred = Ext.create('Deft.promise.Deferred');

    model.load(Rally.util.Ref.getOidFromRef(defect.RevisionHistory), {
        scope: this,
        success: function(record) {
            deferred.resolve(record);
        }
    });

    return deferred;
},

// grabbing the revisions for each defect
_getRevisions: function(record) {
    var deferred = Ext.create('Deft.promise.Deferred');

    record.getCollection('Revisions').load({
        fetch: ['RevisionNumber', 'CreationDate', 'User', 'Description'],
        scope: this,
        callback: function(revisions) {
            deferred.resolve(revisions);
        }
    });

    return deferred;
},

主な違いは最後の 2 つの関数に_getHistoryあります。-_getRevisionsを返す代わりに、コールバック内で返して解決するために でnew Promise(...)遅延オブジェクトを作成する必要がありました。Ext.create('Deft.promise.Deferred');

うまくいけば、これはDeftJSの古いバージョンを使用するというこの問題で他の誰かを助けるでしょう

于 2014-04-09T18:23:18.133 に答える