每个()循环中的jQuery AJAX解决方案

时间:2013-07-28 03:27:45

标签: jquery ajax asynchronous

我注意到当我在.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) <-- This was a logical error
if($result['userCount'] != 0)
    mysql_query("UPDATE userType SET userTypeName='".$_POST['userTypeName']."', isDeleted='".$_POST['isDeleted']."' WHERE userTypeId='".$_POST['userTypeId']."';");
else
    mysql_query("INSERT INTO userType VALUES('', '".$_POST['userTypeName']."', '".$_POST['isDeleted']."');");

echo mysql_error();

dbClose();
?>

我已经读过我可以选择使用同步而不是异步,但我也读过它不是一个好习惯。

那么我如何实际异步完成并修复问题?

3 个答案:

答案 0 :(得分:4)

jQuery的$ .ajax()返回一个jQuery XMLHttpRequest对象(“jqXHR”)。您将此对象存储到“响应”变量中。

你的问题是范围。您将jqXHR的所有 N 存储到相同的“请求”变量中。在循环结束时,“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()调用;它可能需要一些狡猾,但肯定会变得更好。

答案 1 :(得分:0)

您的问题出在这段代码中:

request.done(function(){
    document.location.reload();
});

由于操作是异步的,因此在保存完成之前执行此行,因此在第一次保存完成后,它将执行done逻辑。

您需要创建一个延迟对象数组,然后等待它们全部执行,然后再使用jQuery .when()/.then()函数继续执行逻辑。

这是一个之前的StackOverflow问题,详细说明了如何设置这种情况。请阅读jQuery when each is completede trigger function的接受答案。

答案 2 :(得分:0)

这里发生了一些事情。

  1. 通过在循环中重新使用request变量(在循环外部作用域),循环的每次迭代都会分配一个新对象来请求,覆盖那里的内容。这意味着您只为最后一次迭代设置响应处理程序。

  2. 您的request.done方法重新加载页面,实际上会停止其他请求并... ...

  3. 您正在为循环的每次迭代查找相同的userTypeId,如@Sean所述