17

複数のajaxクエリを同時に実行しているので、最後のクエリが返されるのを待ってから、すべてのajax呼び出しで成功ハンドラーを実行します。簡単な例として、次のことを考慮してください。

$.ajax({//ajax call 1
    url:page1.php,
    success: function(data1){
        //do something with data1
    }
});

....

$.ajax({//ajax call 2
    url:page2.php,
    success: function(data2){
        //do something with data2
    }
});
//consider more than just two concurrent requests

すべてのリクエストが同時に送信されたとしましょう。それらは非同期であるため、異なる時間に戻ります。一方のリクエストが戻るのに100ミリ秒かかり、もう一方のリクエストが戻るのに3000ミリ秒かかるとします。どちらが最初に戻るか最後に戻るかは明らかにわかりません。それらはすべて何らかの方法でDOMを更新し、1回の更新でそれらの変更を一度にビューアに表示したいと思います。どうすればよいですか?

私が考えることができる最善の方法は、data1とdata2をグローバル変数として保存することです。そして、成功が返されるたびにカウントするカウンター変数を用意します。次に、counter == TOTAL_NUM_REQUESTSでupdateAll()のような関数を呼び出し、すべてのグローバル変数を実行して、必要な場所に配置します。しかし、これは厄介でエラーが発生しやすいようです。さらに、それは多くのグローバル変数になります。

私が理想的に望んでいるのは、成功ハンドラーが戻ったときにスリープ状態にし、すべてが返されたものとしてカウントするという条件で、すべてのハンドラーにウェイクアップメッセージを送信すると、実行を再開できるようにすることです。これは最もクリーンなようですが、javascriptlandでこのような機能を認識していません。

誰かがこれについて何か巧妙なアイデアを持っていますか?

回答の更新

以下のリーのおかげで、私は解決策を得ることができました。私の解決策は彼の以下のように見えました。async$.ajax呼び出しに割り当てられた変数のリストを作成します。最初は、これらのajax呼び出しの成功ハンドラーがまだ呼び出されていたので、それらを削除して、作成したこのwhenブロックによって後で呼び出される別の関数に配置しました。results私はこのような関数に渡しました:

var results = [];
results.push(async1);
results.push(async2);
... for all the results ...

$.when.apply(this, results).done(function() {
   for(var i=0;i<arguments.length;i++){
     dataobject=arguments[i][0]
     if(dataobject.variousattribute)
       mySuccessHandlerFirstGuy(dataobject)
     else if(dataobject.anotherattribute)
       mySuccessHandlerSecondGuy(dataobject)
       //etc ....
   }
};

引数オブジェクトは、それが何であるかを理解するために少し手間がかかりました。それは2D配列(リストのリスト)でした。最初のインデックスは、特定のajaxリクエストに対応する返されたオブジェクトを表しています。順調に見えますが、サーバーが検索できるものを返し、それに応じてif/elseブロックを作成するのが最善です。次に、その特定の要素には、そのリスト内に3つの要素があるように見えます。1つ目は、サーバーから返された値、つまり必要な値です。2番目は常に文字列でしたsuccess。これはおそらく呼び出しが機能したかどうかを確認するために使用できます。そして、そのリストの3番目の要素は、最初のリクエストのようです(わかりませんが)。これは私には役に立たなかった。

とにかく、これが将来誰かに役立つことを願っています。そして、私を正しい方向に向けてくれたリーにもう一度感謝します。

4

3 に答える 3

37

jQuery の $.when() 関数を使用して、すべての ajax 呼び出しが終了したときに何かを実行します。

jQuery.when ドキュメント

var async1 = $.ajax({//ajax call 1
    url:page1.php,
    success: function(data1){
        //do something with data1
    }
});

....

var async2 = $.ajax({//ajax call 2
    url:page2.php,
    success: function(data2){
        //do something with data2
    }
});

$.when(async2, async1).done(function(result2, result1) {
    ... do this when both are successful ...
});

質問に応じて追加:

大量の ajax 呼び出しがある場合は、次のように「適用」を使用できます。

var results = [];
results.push(async1);
results.push(async2);
... for all the results ...

$.when.apply(this, results).done(function() {
    ... use 'arguments' array to get results ...
});
于 2013-01-22T18:12:58.453 に答える
0

これはおそらく、すでに提案したものと非常によく似た方法で行うことができます。

まず、グローバル変数var sleep = trueと を作成しますvar request_count = 0request_count次に、約 1 秒ごとにリクエストの総数をチェックするタイマーを開始します。次に、成功関数をインクリメントrequest_counterして、 までループを開始できますsleep == false。次に、タイマーを介して実行されている監視機能がrequest_count == TOTAL_REQUESTSそれを検出すると、 が設定さsleep = falseれ、すべての成功機能はその時点でビジネスを継続します。

于 2013-01-22T18:13:35.880 に答える
-1

簡単な解決策は PreloaderQ モジュールを使用することです

https://www.npmjs.com/package/preloaderq

以下のように使用

var preloader = new PreloaderQ()
preloader.setEmptyCallback(function(){
    //all tasks are finished
})

preloader.setFirstTaskCallback(function(){
    //started first task
})

preloader.enqueueTask('ajax1')

$.ajax({//ajax call 1
    url:page1.php,
    success: function(data1){
        prealoader.dequeueTask('ajax1')
        //do something with data1
    }
});

preloader.enqueueTask('ajax2')

$.ajax({//ajax call 1
    url:page2.php,
    success: function(data2){
        prealoader.dequeueTask('ajax2')
        //do something with data2
    }
});

emptycallback は、両方が終了した後に呼び出されます

于 2017-03-09T01:33:27.593 に答える