详解JavaScript for循环中发送AJAX请求问题
本文探讨在JavaScript的for循环中频繁发送AJAX请求时,因迭代速度过快导致请求被取消的问题。文章提供了两种解决方案:一是使用同步请求确保顺序执行,二是通过每次迭代创建新的XMLHttpRequest对象并封装为函数来保证异步请求的完整性。
问题背景
这种情况在实际开发中并不常见,因为通常存在更优的替代方案。但在处理AJAX时遇到一个有趣现象:当需要在每个循环迭代中发送GET请求时,由于循环执行速度极快,前一个请求尚未完成,下一个迭代便已开始。在Chrome和Firefox浏览器中,除最后一个请求外,其余请求均被取消。面对此问题,有人建议设置延时(但这并非最佳实践),那么是否有其他解决办法?
解决方案一:同步请求
方法众多,例如设置休眠或调整迭代逻辑,这里主要介绍另外两种解决思路。
function creatXMLHttpRequest() {
var xmlHttp;
if (window.ActiveXObject) {
return xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
} else if (window.XMLHttpRequest) {
return xmlHttp = new XMLHttpRequest();
}
}
function disButton(name, actionName, resquestParmName) {
var path = document.getElementById("path").value;
var xmlHttp = creatXMLHttpRequest();
var invoiceIds = new Array();
invoiceIds = document.getElementsByName(name);
// 迭代的速度快于发送请求+收到回复的时间 所以一次get请求都还没有完成就进行了下一次请求
for (i = 0; i < invoiceIds.length; i++) {
var invoiceId = invoiceIds[i].value;
var url = path + "/" + actionName + ".action?" + resquestParmName + "="
+ invoiceId;
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4) {
if (xmlHttp.status == 200) {
var result = xmlHttp.responseText;
if (result == "0") {
document.getElementById("btn" + invoiceId).disabled = "disabled";
}
}
}
}
xmlHttp.open("GET", url, false);
xmlHttp.send(null);
}
}
第一种方案是使用同步AJAX请求。默认情况下,AJAX请求是异步的,因此需要将其设置为false。

通过采用同步AJAX请求,代码会等待服务器响应返回并执行完毕后,再继续执行下一次迭代。不过,官方通常不推荐这种做法。
function creatXMLHttpRequest() {
var xmlHttp;
if (window.ActiveXObject) {
return xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
} else if (window.XMLHttpRequest) {
return xmlHttp = new XMLHttpRequest();
}
}
function disButton(name, actionName, resquestParmName) {
var xmlHttp;
var path = document.getElementById("path").value;
var invoiceIds = new Array();
invoiceIds = document.getElementsByName(name);
// 迭代的速度快于发送请求+收到回复的时间 所以一次get请求都还没有完成就进行了下一次请求
for (i = 0; i < invoiceIds.length; i++) {
xmlHttp = creatXMLHttpRequest();
var invoiceId = invoiceIds[i].value;
var url = path + "/" + actionName + ".action?" + resquestParmName + "="
+ invoiceId;
fu(xmlHttp,url,invoiceId);
}
}
function fu(xmlHttp,url,invoiceId){
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4) {
if (xmlHttp.status == 200) {
var result = xmlHttp.responseText;
if (result == "0") {
document.getElementById("btn" + invoiceId).disabled = "disabled";
}
}
}
}
//
xmlHttp.open("GET", url, true);
xmlHttp.send(null);
}
解决方案二:异步请求与对象创建
由于JS的for循环与ajax非同步运行,因此导致for循环结束了而ajax却还未执行。如果采用的是异步请求的方式,如果每次迭代的时候都去new一个XMLHttpRequest,这样每次请求都能完成,但是结果还是还是不准确,有些程序还未被执行。 明白了,原来是每次迭代去执行几行代码,应该把发送ajax异步请求的代码放在一个函数中,每次迭代就去调用这个函数,这样就行了。
由于JavaScript的for循环与AJAX请求是非同步运行的,往往导致for循环已经结束,而AJAX请求仍在执行中。如果采用异步请求且每次迭代都new一个新的XMLHttpRequest对象,虽然能保证每次请求完成,但结果仍可能不准确,部分程序逻辑可能未被正确执行。

优化建议与总结
经过分析发现,每次迭代执行的几行代码中,应将发送AJAX异步请求的逻辑封装在一个函数中,每次迭代时调用该函数,即可解决问题。
从性能角度来看,对于此类迭代AJAX请求的场景,同步方式的性能似乎更高。
D3.js 比例尺与坐标轴的配置详解
2026-11-05 16:54:46
JavaScript怎么遍历对象的Symbol键和不可枚举属性
2026-11-05 13:13:39
封装一个健壮的JS字符串判空工具函数
2026-11-05 12:16:14
JavaScript合并数组的三种常用方法:concat、扩展运算符与push
2026-11-05 11:22:29
JavaScript立即执行函数(IIFE)是什么及基本语法
2026-11-05 10:51:19
