详解JavaScript for循环中发送AJAX请求问题

作者:异步漫步

时间:2026-10-30

浏览:193

本文探讨在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请求的场景,同步方式的性能似乎更高。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章