1

JavaScript/jQuery でいくつかの機能を実行する必要がありますが、UI をブロックしないようにしたいと考えています。

AJAX は実行可能なソリューションではありません。アプリケーションの性質上、これらの機能は簡単に数千に達します。これを非同期に行うと、ブラウザが強制終了されます。

そのため、ブラウザーが処理する必要がある関数をチェーンする何らかの方法が必要であり、最初の関数が終了した後にのみ次の関数を送信します。

アルゴリズムはこのようなものです

ステップ 2 ~ 15 の場合

HTTP:GET 現在のステップのアイテムの量 (数百から数千の範囲)

すべての項目について、HTTP:結果を取得します

ご覧のとおり、私には 2 つの GET-request-"chains" があり、どうにかして管理する必要があります...特に、最も内側のループは、非同期で行われた場合、ほぼ瞬時にブラウザをクラッシュさせますが、それでもユーザーができるようにしたいと思いますページを操作するため、純粋な (ブロッキング) 同期方法は機能しません。

4

2 に答える 2

4

すべてのリクエストを一度に発行することなく、これを非同期で簡単に実行できます。あなたがする必要があるのは、キューを管理することだけです。以下は、わかりやすくするための疑似コードです。実際の AJAX リクエストに簡単に変換できます。

// Basic structure of the request queue. It's a list of objects
// that defines ajax requests:
var request_queue = [{
    url : "some/path",
    callback : function_to_process_the_data
}];

// This function implements the main loop.
// It looks recursive but is not because each function
// call happens in an event handler:
function process_request_queue () {
    // If we have anything in the queue, do an ajax call.
    // Otherwise do nothing and let the loop end.
    if (request_queue.length) {
        // Get one request from the queue. We can either
        // shift or pop depending on weather you prefer
        // depth first or breadth first processing:
        var req = request_queue.pop();
        ajax(req.url,function(result){
            req.callback(result);
            // At the end of the ajax request process
            // the queue again:
            process_request_queue();
        }
    }
}

// Now get the ball rolling:
process_request_queue();

したがって、基本的には ajax 呼び出し自体を疑似ループに変えます。これは基本的に、再帰的に行われるプログラミングの古典的な継続渡しスタイルです。

あなたの場合、リクエストの例は次のようになります。

request_queue.push({
    url : "path/to/OUTER/request",
    callback : function (result) {
        // You mentioned that the result of the OUTER request
        // should trigger another round of INNER requests.
        // To do this simply add the INNER requests to the queue:

        request_queue.push({
            url : result.inner_url,
            callback : function_to_handle_inner_request
        });
    }
});

幅優先または深さ優先 (シフト vs ポップ) のいずれかでリクエストを処理するオプションがあるだけではないため、これは非常に柔軟です。ただし、splice を使用してキューの途中に追加したり、unshift vs push を使用して優先度の高いリクエストのキューの先頭にリクエストを配置したりすることもできます。

ループごとに複数のリクエストをポップすることで、同時リクエストの数を増やすこともできます。process_request_queue同時リクエストが指数関数的に増加するのを避けるために、ループごとに 1 回だけ呼び出すようにしてください。

// Handling two simultaneous request channels:
function process_request_queue () {
    if (request_queue.length) {
        var req = request_queue.pop();
        ajax(req.url,function(result){
            req.callback(result);
            // Best to loop on the first request.
            // The second request below may never fire
            // if the queue runs out of requests.
            process_request_queue();
        }
    }
    if (request_queue.length) {
        var req = request_queue.pop();
        ajax(req.url,function(result){
            req.callback(result);
            // DON'T CALL process_request_queue here
            // We only want to call it once per "loop"
            // otherwise the "loop" would grow into a "tree"
        }
    }
}
于 2012-11-06T13:25:05.800 に答える
1

その ASYNC を作成し、私が以前に書いた小さなライブラリを使用して、関数呼び出しをキューに入れることができます。

于 2012-11-06T12:12:16.493 に答える