0

注: 簡略化された例..

1000 行のテーブルがあるページがあります。行ごとに、AJAX呼び出しを介してサーバー上で「何らかの作業を行う」必要があり、コールバックでそのテーブル行を更新して完了と伝えます。

最初は、セレクター内で 1000 個の ajax リクエストを起動しようとしました.eachが、ブラウザーがロックされていました。

そこで、内部の ajax カウンターを使用するように変更して、一度に 50 個しか起動しないようにしました。

コードは次のとおりです。

$('#do').click(function () {
    var maxAjaxRequests = 50;
    var ajaxRequests = 0;
    var doneCounter = 0;
    var toDo = $('#mytable tr').length;

    $.each($('#mytable > tr'), function (i, v) {
        while (doneCounter < toDo) {
            if (ajaxRequests <= maxAjaxRequests) {
                ajaxRequests++;
                doAsyncStuff($(this), function () {
                    ajaxRequests--;
                    doneCounter++;
                });
            } else {
                setTimeout(function() {
                }, 1000);
            }
        }
    });
});

function doAsyncStuff(tr, completeCallback) {   
    $.ajax({
        url: '/somewhere',
        type: 'POST',
        dataType: 'json',
        data: null,
        contentType: 'application/json; charset=utf-8',
        complete: function () {
            completeCallback();
        },
        success: function (json) {
            // update ui.
        },
        error: function (xmlHttpRequest, textStatus, errorThrown) {
            // update ui.
        }
    });
}

しかし、ブラウザはまだロックされています。$.ajaxリクエストが (Fiddler 経由で) 正常に戻ってくるのを確認できますが、完全なコールバックにはなりません。したがって、コールバックが返されないため、単にスリープ、ループ、スリープなどです。

doAsyncStuff関数全体を非同期にする必要があると感じていますか?

私が間違っていることについてのアイデアはありますか (または、これを改善するにはどうすればよいですか)?

4

3 に答える 3

1

whileコールバック関数内でループを実行している.eachため、1000よりもはるかに多くのajaxリクエストがあり、最悪の場合は1000*1000です。

各ajaxリクエストを異なる時間で遅らせることができます。

$('#do').click(function () {
    $('#mytable > tr').each(function (i, v) {
        var $this = $(this);
        setTimeout(function () {
            doAsyncStuff($this, function () {
               console.log('complete!');
            });
        }, i * 10);
    });
});
于 2012-08-28T06:56:58.993 に答える
0

WHILEが原因でブラウザがロックされます...無限のループを作成しています。

whileループは、doneCounterが増加するのを待って何度も実行されますが、javascriptエンジンは、しばらくの間スタックしているため、ajaxの成功呼び出しを実行できません...

var callQueue = new Array();
$('#mytable > tr').each(function(key,elem){callQueue.push($(this));});

var asyncPageLoad = function(){
var tr = callQueue.splice(0,1);
$.ajax({
        url: '/somewhere',
        type: 'POST',
        dataType: 'json',
        data: null,
        contentType: 'application/json; charset=utf-8',
        complete: function () {
            completeCallback();
            asyncPageLoad();
        },
        success: function (json) {
            // update ui.
        },
        error: function (xmlHttpRequest, textStatus, errorThrown) {
            // update ui.
        }
    }
};
asyncPageLoad();

これにより、リクエストが1つずつ呼び出されます。必要に応じて、内部でfor()ループを実行して、おそらく5回の呼び出しを行いますか?また、ブラウザに問題がない場合は、量を増やしてください。

于 2012-08-28T07:05:20.600 に答える
0

実際、現在のリクエストが完了したら、新しいリクエストを送信することを好みます。このメソッドを使用して、db テーブルをダンプしました (この作業で)。多分それはアイデアを与える。

このリンクを参照し、すべてのチェック ボックスをオンにして [Dump!] をクリックします。ボタン。ソースコードはここにあります(dumpAll関数を参照)。

于 2012-08-28T07:38:25.297 に答える