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,因此ajax请求比1000多得多,最糟糕的是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的成功调用,因为它卡在while中......

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();

这将一一调用请求。如果您愿意,只需在内部执行一个 for() 循环即可进行 5 次调用?如果浏览器没问题,请增加数量。

于 2012-08-28T07:05:20.600 回答
0

实际上,我更喜欢在当前请求完成后发送新请求。我使用这种方法转储数据库表(在这项工作中)。也许它给出了一个想法。

查看此链接,选中所有复选框并单击转储!按钮。你可以在这里找到源代码(见dumpAll函数)。

于 2012-08-28T07:38:25.297 回答