jQuery中setInterval仅在each循环结束后执行的问题求解
问题根源与解决方案
你遇到的问题核心是同步AJAX(async: false)阻塞了浏览器的事件循环——浏览器在处理同步AJAX时,会暂停所有UI更新、定时器回调这类异步任务,直到所有同步操作全部完成,所以你的setInterval要等到整个each循环跑完才会执行。另外你的定时器用法也有问题:每次循环都会创建新的定时器,还共用全局的id变量,很容易出现逻辑混乱。
解决思路
- 删掉
async: false,改用异步AJAX,避免阻塞事件循环 - 放弃用
each直接循环处理异步任务,改用递归逐个处理选中的复选框,确保每次任务执行时能及时更新UI - 不需要依赖
setInterval,直接在需要更新计数器的时机修改div内容即可,逻辑更清晰高效
修改后的代码示例
function updateCounter($div, count) { $div.html(count); } $(document).ready(function() { // 先收集所有选中的复选框,减少重复DOM查询 const $checkedBoxes = $('div[name="chkstampa' + arg + '"]').filter(function() { return $(this).jqxCheckBox('checked') === true; }); const total = $checkedBoxes.length; let currentCount = 0; let idsfattura = ''; const $counterDiv = $('#div_count'); // 递归处理每个选中的复选框 function processNext() { if (currentCount >= total) return; const $currentBox = $checkedBoxes.eq(currentCount); const isLast = currentCount === total - 1; const idFattura = $currentBox.attr('idFattura'); // 实时更新计数器UI updateCounter($counterDiv, currentCount + 1); idsfattura += ";" + idFattura; $.ajax({ type: "POST", dataType: "html", url: "<?php echo base_url(); ?>/index.php/home/stampa_fatturamultipla", data: { post_idfattura: idFattura, post_tipo: '', post_count: currentCount + 1, post_last: isLast ? 1 : 0, post_idsfattura: idsfattura }, success: function(msg) { currentCount++; if (isLast) { // window.open(msg); document.location.reload(); } else { // 处理下一个任务 processNext(); } }, error: function(XMLHttpRequest, textStatus, errorThrown) { alert("error: " + errorThrown); // 出错后可选择继续处理下一个,或根据需求调整逻辑 currentCount++; processNext(); } }); } // 启动处理流程 if (total > 0) { processNext(); } });
关键改动说明
- 提前收集所有选中的复选框,避免循环中重复查询DOM,提升性能
- 用递归替代
each循环,确保每个AJAX请求完成后再处理下一个任务,同时能实时更新计数器 - 移除同步AJAX,不再阻塞事件循环,UI更新和异步任务能正常执行
- 直接在处理每个任务前更新计数器,逻辑更直观,无需依赖定时器
内容的提问来源于stack exchange,提问作者luna80
相关产品推荐
相关产品推荐

