无法在AJAX请求success函数中访问外部计数器变量
问题原因分析
你遇到的核心问题是AJAX请求的异步特性导致的:
AJAX默认是异步执行的——当你在循环里发送AJAX请求后,JavaScript不会等待请求返回结果,而是直接跳过回调函数,继续执行后面的runCount++和判断逻辑。
所以实际执行顺序是:
- 循环里一口气发送所有AJAX请求
- 立刻执行所有循环内的
runCount++,直接把runCount加到updateCount,提前打印了"Done" - 等服务器返回结果后,才会执行success回调里的
runCount++,但这时候runCount已经超过目标值,你就误以为回调里的自增没生效
另外要说明:success回调里是可以访问runCount的(JavaScript闭包特性),只是执行时机太晚了。
修复方案
方案一:用Promise.all统一处理异步请求(推荐,更现代可靠)
把每个AJAX请求包装成Promise,等所有请求都完成后再统一判断结果:
var updateCount = 10; var runCount = 0; // 存储所有AJAX请求的Promise实例 var ajaxTasks = []; $('#main-table .changed').not("[value='0']").closest('tr').each(function(e){ if($(this).closest('tr').find('.changed').val() == 1){ var row = $(this).closest('tr'); var notes = row.find('input[name="notes"]').val(); var category = row.find('select[name="category"]').val(); var fileId = row.find('select[name="file"]').val(); var fileRow = row.find('.file-id').val(); var quarter_id = row.find('.quarter-id').val(); // 将AJAX包装为Promise var task = new Promise((resolve, reject) => { $.ajax({ url: '/myurl', type: "POST", data: {_token: CSRF_TOKEN, 'file_row' : fileRow, 'files' : fileId, 'notes': notes, 'category' : category, 'type' : type, 'quarter': quarter_id, 'row_count':updateCount}, success: function(data){ if(data == 0){ console.log("yes"); runCount++; } resolve(); // 标记请求完成 }, error: () => reject() // 处理请求失败的情况 }); }); ajaxTasks.push(task); }; }); // 等所有请求都完成后执行后续逻辑 Promise.all(ajaxTasks).then(() => { if(runCount == updateCount){ console.log("Done"); } else { console.log(`部分请求未成功,成功完成:${runCount} 次`); } }).catch(() => { console.log("存在请求失败的情况"); });
方案二:调整回调内的计数逻辑(适合不想用Promise的场景)
移除循环内的runCount++,只在success回调里计数,并且每次计数后检查是否达到目标值:
var updateCount = 10; var runCount = 0; $('#main-table .changed').not("[value='0']").closest('tr').each(function(e){ if($(this).closest('tr').find('.changed').val() == 1){ var row = $(this).closest('tr'); var notes = row.find('input[name="notes"]').val(); var category = row.find('select[name="category"]').val(); var fileId = row.find('select[name="file"]').val(); var fileRow = row.find('.file-id').val(); var quarter_id = row.find('.quarter-id').val(); $.ajax({ url: '/myurl', type: "POST", data: {_token: CSRF_TOKEN, 'file_row' : fileRow, 'files' : fileId, 'notes': notes, 'category' : category, 'type' : type, 'quarter': quarter_id, 'row_count':updateCount}, success: function(data){ if(data == 0){ console.log("yes"); runCount++; // 每次自增后立即检查是否完成 if(runCount == updateCount){ console.log("Done"); } } } }); // 删掉这里的runCount++!! }; });
内容的提问来源于stack exchange,提问作者user7070541
相关产品推荐
相关产品推荐

