0

我注意到当我在 .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();
?>

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

那么我如何真正做到异步完成并解决问题呢?

4

3 回答 3

4

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

你的问题是范围。您将所有N个 jqXHR 存储到同一个“请求”变量中。在你的循环结束时,“请求”只指向最后一个 jqXHR,因此 .done() 只会在你的最后一个请求完成时被调用。

正如 Karl Anderson 指出的那样,您应该将所有 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() 调用;它可能需要一些技巧,但肯定会变得更好。

于 2013-07-28T03:58:34.283 回答
0

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

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

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

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

这是以前的 StackOverflow 问题,详细说明了如何设置这种情况。当每个完成触发功能时,请阅读 jQuery 接受的答案。

于 2013-07-28T03:43:39.750 回答
0

这里发生了几件事。

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

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

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

于 2013-07-28T03:47:01.387 回答