防止AJAX队列阻止浏览器

注意:简化示例..

我有一个包含1000个表行的页面。 对于每一行,我需要通过AJAX调用在服务器上“做一些工作”,然后在回调中,更新表格行说完了。

最初我尝试在.each选择器内启动1000个ajax请求,但浏览器已锁定。

所以我改变它尝试使用内部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函数需要异步?

关于我做错了什么(或者我如何做得更好)的任何想法?

你在.each回调函数中进行了一个while循环,因此有超过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); }); }); 

浏览器因为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(); 

这将逐个调用请求。 如果你愿意,只需在里面做一个for()循环就可以进行5次调用? 如果浏览器没问题,请增加金额。

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

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