如何以连续顺序执行多个链接的$ .post()调用?

如何以连续顺序执行多个链接的$ .post()调用?

问题描述:

我需要触发1-3个不同的 $。post()请求,它是1个呼叫,2个连续呼叫还是3个连续呼叫取决于一些基本的用户选择。经过前面的彻底完成每次调用只能启动

I need to trigger 1 to 3 different $.post() requests, and whether it's 1 call, 2 consecutive calls, or 3 consecutive calls is decided by some basic user selection. Each call must only start after the previous is completely finished.

我处理的3个简单的行为例 - 用户,被赠予复选框1,复选框2,和继续按钮,选择

I am dealing with 3 simple behavior cases -- the user, being presented with "Checkbox 1," "Checkbox 2," and a "Continue" button," opts to


  1. 不选择任何内容,然后按继续按钮,进行XHR呼叫到'/remote.php',

  2. 用户选择仅选择复选框1 复选框2,然后按继续按钮,会调用绑定到复选框1的 $。post()函数1 $。post()函数2 绑定到Checkbox 2,然后对'/remote.php'进行XHR调用,

  3. 或者用户同时选中Checkbox 1 + 2,然后按Continue,这将调用 $。post()函数1 ,然后调用 $。post()函数2 ,然后对 /remote.php'。

  1. Select nothing and then press "Continue" button, which makes an XHR call to '/remote.php',
  2. The user opts to only select "Checkbox 1" or "Checkbox 2," and then presses "Continue" button, which calls $.post() Function 1 that is bound to Checkbox 1, or $.post() Function 2 that is bound to Checkbox 2, and then makes an XHR call to '/remote.php',
  3. Or the user selects both Checkbox 1 + 2 and then presses Continue, which calls $.post() Function 1, then calls $.post() Function 2, and then makes an XHR call to '/remote.php'.

我需要确保继续按钮 $。 post()函数不会触发直到复选框绑定的 $。post()函数触发并完成。

I need to make sure that the Continue-button $.post() function does not fire until the Checkbox-bound $.post() functions fire and complete.

问题是,如果选中了复选框1和复选框2,然后按了继续按钮,就像我了解这一点,加载顺序应该是:

The problem is that if Checkbox 1 is selected and Checkbox 2 is selected, and then the Continue button is pressed, as I understand it, the loading order should be:


  1. 复选框1绑定 $。post()请求触发并完成,然后

  2. 复选框2绑定 $。post()请求触发并完成,然后

  3. 继续按钮绑定 $。post()触发,并且在绑定到继续按钮绑定功能的函数结尾通过AJAX更改页面

  1. Checkbox 1 bound $.post() request fires and completes, then
  2. Checkbox 2 bound $.post() request fires and completes, then
  3. Continue button bound $.post() fires, and pages is changed via AJAX at the end of the function tied to "Continue" button bound function.

因此,结果应如下所示:

So, where the result should look like:

XHR finished loading: POST "/cart.php?action=add&product_id=1280".
XHR finished loading: POST "/cart.php?action=add&product_id=1284". 
XHR finished loading: POST "/remote.php".

它经常这样出现:

XHR finished loading: POST "/cart.php?action=add&product_id=1280".
XHR finished loading: POST "/remote.php".
XHR finished loading: POST "/cart.php?action=add&product_id=1284". 

因此,当页面由于 last / Continue-按钮功能,既未执行Checkbox 1或Checkbox 2操作,也未执行两个操作之一,或两者都在后端注册(即添加到购物车),但未反映在AJAXified DOM中,因为它们应作为最终操作AJAX在先前的$ .post()调用完成之前触发并完成。

So when the page changes due to the AJAX at the end of the "last"/"Continue-button function, either neither of the Checkbox 1 or Checkbox 2 actions have taken place, or one of the two or both do register in the backend (ie, added to cart) but do not reflect in the AJAXified DOM as they should as the final AJAX fires and completes before the previous $.post() calls have completed.

HTML是基本的:

<form method="post" action="#" onsubmit="newChooseShippingProvider(); return false;">
    <label for="delSigCheck" class="del-sig-text"><input id="delSigCheck" type="checkbox" onchange="addDelSigToCart();" title="Add Delivery Signature"></label>
    <label for="addInsCheck" class="ins-add-calc"><input id="addInsCheck" type="checkbox" onchange="addInsToCart();" title="Add Delivery Signature" data-ins-id="1284"></label>
    <input type="submit" value="Continue" class="btn Small">
</form>



Javascript / jQuery



这是我最近尝试的第4或第5,但仍然无法正常工作:

The Javascript/jQuery

This is my latest--4th or 5th--attempt, and still does not work:

function addDelSigToCart() {
    $('#delSigCheck').toggleClass('checked');
}
function addInsToCart() {
    $('#addInsCheck').toggleClass('checked');
}
function newChooseShippingProvider() {
    var originalCheckout = ExpressCheckout.ChooseShippingProvider();
    if ($('.ShippingProviderList .radio span').hasClass('checked')) {
        var addInsCheck = $('#addInsCheck').hasClass('checked');
        var delSigCheck = $('#delSigCheck').hasClass('checked');
        var insId = $('#addInsCheck').attr('data-ins-id');
        var addDelSigUrl = '/cart.php?action=add&product_id=1280';
        var addInsUrl = '/cart.php?action=add&product_id=' + insId;
        if (delSigCheck && addInsCheck) {
            $.post(addDelSigUrl, function() {
                $.post(addInsUrl, function() {
                    originalCheckout;
                });
            });
        } else if (!delSigCheck && !addInsCheck) {
            originalCheckout;
        } else if (delSigCheck && !addInsCheck) {
            $.post(addDelSigUrl, function() {
                originalCheckout;
            });
        } else if (!delSigCheck && addInsCheck) {
            $.post(addInsUrl, function() {
                originalCheckout;
            });
        }
    } else {
        originalCheckout;
    }






我尝试过的



我已经经历了多个链接 $。post()调用的版本,但是似乎没有任何效果


What I've Tried

I've gone through several version of chaining the $.post() calls, but nothing seems to work consistently.

我现在使用的是什么,并且对于广泛测试来说最适合我的是使用 setTimeout 延迟链接函数,例如:

What I am using now and what seems to work the best for me with extensive testing is using setTimeout to chain the function with some delay, like this:

    ...
    if (delSigCheck && addInsCheck) {
        $.post(addDelSigUrl);
        setTimeout(function() {
            $.post(addInsUrl);
            setTimeout(function() {
                ExpressCheckout.ChooseShippingProvider();
            }, 1300);
        }, 1300);
    } else if ...

上面的这个版本就是我现在使用的版本,因为它似乎提供了最一致的结果,所以看到脚本的加载通常为1,2,3,然后是基于函数1和2进行了适当更改的DOM AJAXified。但是,我认为setTimeout不能像即使当我将其增加到5000或10000时,该操作也会立即执行,并且不会发生延迟(至少可以肯定没有接近5-10秒的时间)。

And this version above is what I'm using now, as it seems to give the most consistent results, seeing the scripts load typically as 1,2,3, followed by a DOM AJAXified with appropriate changes based on function 1 and 2. However, I don't think the setTimeout is working as even when I increase it to 5000 or 10000, the action is performed "instantaneously" and no delay takes place (at least certainly nothing close to 5-10 seconds).

我还尝试将函数放入 $。post()的成功回调中:

I've also tried putting the functions inside $.post()'s success callback:

    ...
    if (delSigCheck && addInsCheck) {
        $.post(addDelSigUrl, function() {
            setTimeout(function() {
                $.post(addInsUrl, function() {
                    setTimeout(function() {
                        originalCheckout;
                    }, 1300);
                });
            }, 1300);
        });
    } else if ...

最后我也尝试过:

$.when($.post(addDelSigUrl)).then(originalCheckout);

以及 .done 成功:,但没有一个起作用,并且$ .posts()的加载以意外顺序失败。

as well as .done and success: but none of it works, and the $.posts()'s load in an unexpected order, failing.


  1. 我在做什么错了?

  2. 如何使它加载1次完全,然后2次完全加载,然后只有3次触发和加载?



UPDATE 1:



我刚刚尝试了 jfriend00的答案

            $.post(addDelSigUrl, { cache: false }).then(function(data1) {
                //CONSOLE.LOGing HERE
                console.log(data1);
                return $.post(addInsUrl, { cache: false });
            }).then(function(data2) {
                //CONSOLE.LOGing HERE
                console.log(data2);
                return originalCheckout;
            });

但是它仍然导致:

XHR finished loading: POST "/cart.php?action=add&product_id=1280".
XHR finished loading: POST "/remote.php".
XHR finished loading: POST "/cart.php?action=add&product_id=1284". 

和两个console.log在第一个 XHR ...之后立即触发,然后/ remote。 php触发(尽管应该作为originalCheckout的一部分持续触发),然后触发第三个XHR。

and both console.logs fire immediately after the first "XHR ...", THEN /remote.php fires (though it should fire last as part of originalCheckout), THEN the 3rd XHR fires.

现在,我们通过 .then()以正确的顺序触发并加载了XHR,我遇到的第二个问题是第三个XHR code> /remote.php 使用后端的数据通过AJAX更新DOM。该数据的一部分是第一和第二个 $。posts

Now that we got the XHRs firing and loading in the correct order via .then(), the second part of the problem I am having is that the 3rd XHR to /remote.php updates the DOM via AJAX with data from the backend. Part of that data is the 1st and 2nd $.posts.

我认为第3个AJAX调用正在触发并完成毫秒,然后才通过服务器端PHP对后端执行某些操作,因此,超过50%的时间,通过第3次AJAX调用进行的DOM更新丢失了第1次和/或第2次调用的数据(最常见的DOM更改包括Checkbox 1 / AJAX调用1,但没有2)。

I think the 3rd AJAX call is firing and completing milliseconds before some action is taken on the backend via server-side PHP, and because of this more than 50% of the time, the DOM update via the 3rd AJAX call is missing the data from the 1st and/or 2nd call (most often the DOM changes include Checkbox 1/AJAX call 1, but not 2).

如何解决此问题?我尝试过setTimeout,但是即使将其设置为30000,它似乎也无法正常工作,一旦第1/2次完成,第3 AJAX就会触发。

How can I fix this? I've tried setTimeout but it doesn't seem to work as even when I set it to like 30000, the 3rd AJAX fires as soon as the 1st/2nd complete.

最新的前端代码:

function newChooseShippingProvider() {
    if ($('.ShippingProviderList .radio span').hasClass('checked')) {
        var addInsCheck = $('#addInsCheck').hasClass('checked');
        var delSigCheck = $('#delSigCheck').hasClass('checked');
        var insId = $('#addInsCheck').attr('data-ins-id');
        var addDelSigUrl = '/cart.php?action=add&product_id=1280';
        var addInsUrl = '/cart.php?action=add&product_id=' + insId;
        if (delSigCheck && addInsCheck) {
            $.post(addDelSigUrl).then(function(data1) {
                return $.post(addInsUrl);
            }).then(function(data2) {
                return ExpressCheckout.ChooseShippingProvider();
            });
        } else if (!delSigCheck && !addInsCheck) {
            ExpressCheckout.ChooseShippingProvider();
        } else if (delSigCheck && !addInsCheck) {
            $.post(addDelSigUrl).then(function(data1) {
                return ExpressCheckout.ChooseShippingProvider();
            });
        } else if (!delSigCheck && addInsCheck) {
            $.post(addInsUrl).then(function(data1) {
                return ExpressCheckout.ChooseShippingProvider();
            });
        }
    } else {
        ExpressCheckout.ChooseShippingProvider();
    }
}


在序列化jQuery ajax操作的最简单方法是使用内置的promises:

The simplest way to sequence jQuery ajax operations is to use the built-in promises:

$.post(...).then(function(data1) {
    return $.post(...);
}).then(function(data2) {
    return $.post(...);
}).then(function(data3) {
    // everything done here
});

工作演示,向您显示精确的排序: http://jsfiddle.net/jfriend00/zcfr2xy0/

Working demo that shows you the precise sequencing: http://jsfiddle.net/jfriend00/zcfr2xy0/

好,看来问题是您在执行此操作:

OK, it appears that the problem is that you're doing this:

var originalCheckout = ExpressCheckout.ChooseShippingProvider();

然后,您认为以后的某个时间,您可以这样做:

And, then you think that sometime later, you can just do:

originalCheckout;

这将以某种方式执行前者。事实并非如此。您的 ExpressCheckout.ChooseShippingProvider()函数将立即执行,并将执行该函数的返回结果分配给 originalCheckout

and that will somehow execute the former. That's not the case. Your ExpressCheckout.ChooseShippingProvider() function is executed immediately and the return result from executing that function is assigned to originalCheckout.

您根本不能那样做。当在函数名称后有()时,表示立即执行。我建议您仅将 originalCheckout; 的所有实例替换为 ExpressCheckout.ChooseShippingProvider();

You simply can't do it that way. When you have () after a function name, that means to execute it NOW. I would suggest that you just replace all instances of originalCheckout; with ExpressCheckout.ChooseShippingProvider();.