每个()循环中的jQuery AJAX解决方案
我注意到当我在.each()循环中使用jQuery中的AJAX时遇到问题。 脚本执行时,仅更新数据库中的第一条记录。
这是我的脚本:
function save(){ var _userTypeId; var _userTypeName; var _isDeleted; var request; $("tr.recUserType").each(function(){ $this = $(this); _userTypeId = $this.find("#userTypeId").html(); _userTypeName = $this.find("#userTypeName").val(); _isDeleted = $this.find("#isDeleted").val(); request = $.ajax({ url: "save.php", type: "POST", data: {userTypeId: _userTypeId, userTypeName: _userTypeName, isDeleted: _isDeleted} }); }); request.done(function(){ document.location.reload(); }); request.fail(function(){ alert("Request Failed!"); }); }
以及save.php的内容:
<?php include_once "globals.php"; dbConnect(); $isExisting = mysql_query("SELECT COUNT(userTypeId) AS userCount FROM userType WHERE userTypeId='".$_POST['userTypeId']."';"); $result = mysql_fetch_array($isExisting); //original: if(!$result['userCount'] = 0)
我已经读过我可以选择使用同步而不是异步,但我也读过它不是一个好习惯。
那么我如何实际异步完成并修复问题呢?
jQuery的$ .ajax()返回一个jQuery XMLHttpRequest对象(“jqXHR”)。 您将此对象存储到“响应”变量中。
你的问题是范围。 您将所有N个jqXHR存储到相同的“请求”变量中。 在循环结束时,“request”仅指向最后一个jqXHR,因此只有在LAST请求完成时才会调用.done()。
正如Karl Anderson指出的那样,你应该将所有的jqXHR存储到一个数组中,然后一旦所有的jqXHR完成[异步]就执行一个回调。
var XHRs = []; // ... $("tr.recUserType").each(function() { $this = $(this); _userTypeId = $this.find("#userTypeId").html(); _userTypeName = $this.find("#userTypeName").val(); _isDeleted = $this.find("#isDeleted").val(); XHRs.push($.ajax({ url: "save.php", type: "POST", data: {userTypeId: _userTypeId, userTypeName: _userTypeName, isDeleted: _isDeleted} })); }); $.when(XHRs).then(function() { document.location.reload(); });
另外,避免使用$ .ajax()的“async:false”的美味诱惑。 浏览器将被强制挂起,直到请求完成,这很糟糕。 您几乎总是可以异步完成$ .ajax()调用; 它可能需要一些狡猾,但肯定会变得更好。
您的问题出在这段代码中:
request.done(function(){ document.location.reload(); });
由于操作是异步的,因此在保存完成之前执行此行,因此在第一次保存完成后,它将执行done
逻辑。
您需要创建一个延迟对象数组,然后等待它们全部执行,然后使用jQuery .when()/.then()
函数继续执行逻辑。
这是一个之前的StackOverflow问题,详细说明了如何设置这种情况。 当每个完成触发function时,请阅读jQuery的接受答案。
这里发生了一些事情。
-
通过在循环中重用
request
变量(在循环外部作用域),循环的每次迭代都会分配一个新对象来请求,覆盖那里的内容。 这意味着您只需为最后一次迭代设置响应处理程序。 -
您的
request.done
方法重新加载页面,实际上将暂停其他请求和… -
如@Sean所述,您正在为循环的每次迭代查找相同的
userTypeId