如何确保在继续执行之前完成jQuery Each语句的执行?

3
我的代码如下所示:
$(".qtyfield").each(function (index) {
    if (this.value != "" && this.value > 0) {
        var fieldname = this.id;
        countme = countme + 1;
        var tmpProductID = fieldname.split("_")
        var ProductID = tmpProductID[1];
        var ShowPrice = $(this).closest('td').prev('td').text();
        var Quantity = this.value;
        ShowPrice = ShowPrice.replace("$", "");
        isItemInCart(ProductID).done(function () {
            if (isItemInCartVar) {
                updateQuantityByProductID(ProductID, Quantity);
            }
            else {
                addToCartWithQty(ProductID, ShowPrice, Quantity);
            }

        });
        this.value = '';
    }
});

我需要确保在运行任何后续语句之前,此代码块(包括所有ajax调用)都已完成。
一些要点:
1. `isItemInCart` 是一个带有 Ajax 调用的函数。 2. `updateQuantityByProductID` 是一个带有 Ajax 调用的函数。 3. `addToCartWithQty` 是一个带有 Ajax 调用的函数。 4. 我不知道每个集合中有多少项(可能会改变)。
3个回答

2
我会重构代码,使each循环在服务器端运行。这样,您可以在客户端准备数组,使用ajax(使用唯一的调用)发送它,然后在服务器上解包它,其中您将拥有each循环。 如果你的每个循环有数十亿个元素呢?将其乘以html头的长度。 相反,您可以像这样准备数组。
var serverSide = [];

$(".qtyfield").each(function (index) {

    serverSide.push("the data you need");

});

你可以将它作为 JSON 字符串发送。
var myArg = JSON.stringify(serverSide)

或者是逗号分隔的列表(用于更简单的结构)
var myArg = serverSide.join(',');

并且具有独特的Ajax调用,可以返回任何值/错误消息。
$.post("link", myArg).success(function(data){ alert("data"); })

我不知道你使用的是哪种服务器端支持,但如果你正在使用PHP,你可以使用json_decode解码JSON字符串。

如果你正在使用C#,你可能需要查看JSON.net

无论哪种方式,这样做会让你拥有更多的灵活性。相反,虽然在客户端进行每个循环是可行的,但这并不是最好的解决方案。Ajax调用具有头文件。


2
我的解决方案是将所有逻辑整合到一个单一的调用中,比如updateCart()
在客户端,您需要创建一个需要更新的产品列表,例如:
[
  {productId: 123, quantity: 2, price: 123},
  {productId: 456, quantity: 1, price: 200}
]

这些数据会被发送到服务器端,此时会更新会话数据中的新数量。基本上,服务器端的代码将执行与您所有单个调用相同的逻辑,但速度更快,因为只有一个请求。
单个请求还降低了会话锁争用的可能性,提高了购物车状态的一致性。
在客户端,只有一个回调函数的优点,而不必创建需要同步的单独请求管道(即非常麻烦)。

确实,比我使用延迟对象的解决方案更好。 - schellmax

0
寻找jQuery延迟对象。每个$.ajax调用都会返回一个“promise”对象,您可以等待其被解决:
var promise1 = $.ajax(...)
var promise2 = $.ajax(...)

然后等待它们被解决:

$.when(promise1, promise2).then(function(){
  //ready to rumble
});

正如您所提到的,您不知道每个集合中有多少项,只需将每个 Promise 推入一个数组中,然后可以在 $.when 中使用它,如下所示:

var promises = [];
promises.push($.ajax(...));
$.when.apply(this, promises).then(function(){...});

我在这里经常看到这样的东西,但不太确定我需要做什么才能将其应用到我的代码中。你能帮忙吗? - TRaymond
我会尝试。看起来你已经在使用deferreds,因为'isItemInCart'与'done()'一起使用。现在你应该让其他函数(updateQuantityByProductID、addToCartWithQty)也返回一个promise,并将它们全部推入一个数组中,就像我在帖子中提到的那样。如果需要进一步的帮助,我建议你把相关部分放在jsfiddle里面。 - schellmax
请注意,仅当您的应用程序架构确实需要将此过程拆分为客户端不同的函数时,才应执行此操作。否则,我建议使用此处发布的其他解决方案,在服务器端处理所有内容(并可能添加数据库事务)。 - schellmax
我不完全确定我是否正确地使用它们 :) 所有我看到的例子似乎都不能按照我需要的方式工作。重构以便将所有数据传递到服务器似乎是最好的选择,而不是可能有50多个服务器调用。我的所有ajax请求都调用asp.net Web服务。 - TRaymond

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接