0

ハンドラー (コールバック)、処理するオブジェクト、およびオブジェクトにデータを収集する 4 つの関数があります。私の場合、4 つのデータ リトリーバーを非同期的に呼び出し、4 つすべての実行が完了したら、結果のオブジェクトを処理します (次のようなもの)。

var data = {};

function handle (jsObj) {}

// data retrieving
function getColorData () {}
function getSizeData () {}
function getWeightData () {}
function getExtraData () {}

data.color = getColorData();
data.size = getSizeData();
data.weight = getWeightData();
data.extra = getExtraData();

handle( data );

もちろん、このコードは正しく動作しません。また、データ取得関数を連鎖させると、次々と呼び出されてしまいますよね?4 つの関数はすべて非同期で呼び出す必要があります。実行時間が長すぎて 1 つずつ呼び出すことができないためです。

更新しました:

皆さんの提案に感謝します!私は を好み$.Deferred()ましたが、必要な方法で機能させるのは少し難しいと感じました。私が必要としているのはview、4 種類のデータ ( extraDatacolorDatasizeData& weightData) を必要とする を非同期的に作成することであり、3 つのオブジェクトAppUtils&がありToolsます。

簡単な説明:は、コールバックとして渡されたview呼び出しによって作成されます。の本体のコールバックはのみ呼び出されます。コールバックとして渡される前に呼び出されます。App.getStuffApp.handleStuffApp.getStuff$.when(App.getExtraData(), App.getColorData(), App.getSizeData(), App.getWeightData())Utils.asyncRequestTools.parseResponse

App.get*Data()では、ここでの問題は、それぞれの内部およびそれぞれから 4 つの遅延オブジェクトを作成する必要return deferred.promise()があるかどうかです。そしてdeferred.resolve()、注文の最後の関数に入れるべきですか(Tools.parseResponseApp.getExtraDataの例では)?

var view,
    App,
    Utils = {},
    Tools = {};

// Utils
Utils.asyncRequest = function (path, callback) {
    var data,
        parseResponse = callback;

    // do something with 'data'

    parseResponse( data );
};

// Tools
Tools.parseResponse = function (data) {
    var output = {};

    // do something to make 'output' from 'data'

    /* So, should the deferred.resolve() be done here? */
    deferred.resolve(output);
    /// OR   deferred.resolve();
    /// OR   return output;
};

// App
App = {
    // Only one method really works in my example
    getExtraData : function () {
        var deferred = new jQuery.Deferred();

        Utils.asyncRequest("/dir/data.txt", Tools.parseResponse);

        return deferred.promise();
    },
    // Others do nothing
    getColorData  : function () { /* ... */ },
    getSizeData   : function () { /* ... */ },
    getWeightData : function () { /* ... */ }
};
App.getStuff = function (callback) {
    $.when( 
        App.getExtraData(), 
        App.getColorData(), 
        App.getSizeData(), 
        App.getWeightData()
    )
     .then(function (extraData, colorData, sizeData, weightData) {
        var context,
            handleStuff = callback;

        // do something to make all kinds of data become a single object

        handleStuff( context );
    });
};
App.handleStuff = function (stuff) { /* ... */ };

/// RUN
view = App.getStuff( App.handleStuff );

上記の例のコードが機能するとは思っていませんでした。これは説明のためのものです。

私は長い間静かにこれを解決しようとしてきましたが、まだ結果が得られません。残念ながら、これに関するドキュメントjQuery.Deferred()と議論は役に立ちませんでした。ですから、どんな助けやアドバイスもいただければ幸いです。

4

3 に答える 3

0

このシナリオで私が提案できるのは、そのようなものです。このような関数を書く

var completed = 0;
checkHandler = function() {
  if(completed == 4) {
    handle(data);
  }
}

ここで、completed は、受信する必要がある肯定的なコールバックの数です。すべての関数がコールバックを受け取るとすぐに、「完了」カウンターをインクリメントして checkHandler 関数を呼び出すことができます。これで完了です。

例では

function getColorData() {
   $.get('ajax/test.html', function(data) {
      completed++;
      checkHandler();
   });
}
于 2013-03-29T13:18:33.947 に答える
0

あなたが探しているのはPromises / Deferredsだと思います。

promise を使用すると、次のように記述できます。

when(getColorData(), getSizeData(), getWeightData(), getExtraData()).then(
    function (colorData, sizeData, weightData, extraData) {
        handle(/*..*/);
    }
)

関数は、get*Data()非同期呼び出しが完了すると満たす promise を返します。

元:

function getData() {
    var promise = new Promise();
    doAjax("getData", { "foo": "bar" }, function (result) {
        promise.resolve(result);
    });
    return promise;
}

すべてのプロミスが解決された場合、プロミスの結果whenを呼び出します。then

jQuery には OK の実装があります: http://api.jquery.com/jQuery.when/

于 2013-03-29T13:14:57.727 に答える
0

概念的には、非同期呼び出しが完了するたびにインクリメントされるカウンターを使用します。メインの呼び出し元は、すべての非同期呼び出しによってカウンターがインクリメントされた後に続行する必要があります。

于 2013-03-29T13:16:07.570 に答える