JQuery Ajax同页多调用非异步问题:循环阻塞点击事件Ajax执行
解决循环中Ajax阻塞后续点击事件请求的问题
这个问题我之前也踩过坑,核心原因有两个:
- 浏览器对同一域名下的并发HTTP请求数有限制(大部分浏览器默认是6个左右),你用
$.each循环一次性发起大量Ajax请求,会把所有并发槽占满,后续点击事件触发的请求只能排队等待前面的请求全部完成才能执行。 - 虽然Ajax本身是异步的,但
$.each是同步执行的,会在瞬间把所有请求都塞进浏览器的请求队列里,直接占满并发额度。
下面给你几个可行的解决方案,按推荐程度排序:
1. 控制并发请求数量(最优解)
不要一次性发起所有请求,而是分批次执行,比如一次只发3个请求,等这批请求全部完成后再发下一批。这样既能保证循环里的请求正常执行,也能给点击事件的请求留出并发名额。
用Promise来实现批量控制的代码示例:
$(document).ready(function () { const $elements = $(".saldo-load"); const batchSize = 3; // 每次并发3个请求 let currentIndex = 0; function processBatch() { if (currentIndex >= $elements.length) return; const batch = $elements.slice(currentIndex, currentIndex + batchSize); currentIndex += batchSize; // 把当前批次的请求转为Promise数组 const requests = batch.map(function(i, x) { return $.ajax({ datatype: "json", type: "get", url: "/revendedor/myMethod/" }).done(function(data) { console.log('loop'); console.log(data); }); }); // 等当前批次所有请求完成后,再处理下一批 Promise.all(requests).then(processBatch); } // 启动批量处理 processBatch(); });
2. 给请求添加延迟,分散发起时间
如果不想控制并发数,可以给每个请求之间加个小延迟,避免瞬间发起大量请求,这样浏览器的请求队列不会一下子被占满,点击事件的请求就能插进去执行。
代码示例:
$(document).ready(function () { $(".saldo-load").each(function(i, x) { // 每个请求延迟i*200毫秒发起,分散请求时间 setTimeout(() => { $.ajax({ datatype: "json", type: "get", url: "/revendedor/myMethod/", success: function (data) { console.log('loop'); console.log(data); } }); }, i * 200); }); });
注意:延迟时间可以根据实际情况调整,200毫秒是个比较适中的值,既能分散请求,又不会让总等待时间太长。
3. 合并请求(如果业务允许)
如果这些循环里的请求都是获取类似的数据,最好的方法是后端提供一个批量接口,把所有需要的参数一次性传给后端,后端返回批量结果。这样只需要发起1个请求,既解决了并发阻塞问题,也减轻了服务器压力。
比如把所有需要处理的标识收集起来,传给后端:
$(document).ready(function () { // 假设每个.saldo-load元素有一个id属性作为参数 const ids = $(".saldo-load").map(function() { return $(this).attr("id"); }).get(); $.ajax({ datatype: "json", type: "get", url: "/revendedor/myBatchMethod/", data: { ids: ids.join(",") }, // 把id列表传给后端 success: function (data) { // 遍历返回的批量结果,更新对应的元素 data.forEach(function(item, index) { console.log('batch result'); console.log(item); // 这里可以根据item更新对应的.saldo-load元素 $($(".saldo-load")[index]).text(item.saldo); }); } }); });
这种方法需要后端配合修改接口,但从性能和体验上来说是最好的。
额外提示
- 可以在浏览器的开发者工具(Network面板)里查看请求的状态,会看到很多请求处于
Pending状态,这就是因为并发数限制导致的排队。 - 如果点击事件的请求非常重要,也可以考虑给它设置更高的优先级,但这需要后端配合(比如设置HTTP头),或者用
fetchAPI的priority: 'high'属性(不过这个属性目前还不是所有浏览器都支持)。
内容的提问来源于stack exchange,提问作者AlvaroCryptogram
相关产品推荐
相关产品推荐

